xref: /aosp_15_r20/external/toolchain-utils/crosperf/results_cache_unittest.py (revision 760c253c1ed00ce9abd48f8546f08516e57485fe)
1*760c253cSXin Li#!/usr/bin/env python3
2*760c253cSXin Li# -*- coding: utf-8 -*-
3*760c253cSXin Li
4*760c253cSXin Li# Copyright 2011 The ChromiumOS Authors
5*760c253cSXin Li# Use of this source code is governed by a BSD-style license that can be
6*760c253cSXin Li# found in the LICENSE file.
7*760c253cSXin Li
8*760c253cSXin Li"""Module of result cache unittest."""
9*760c253cSXin Li
10*760c253cSXin Li
11*760c253cSXin Liimport io
12*760c253cSXin Liimport os
13*760c253cSXin Liimport pickle
14*760c253cSXin Liimport re
15*760c253cSXin Liimport shutil
16*760c253cSXin Liimport tempfile
17*760c253cSXin Liimport unittest
18*760c253cSXin Liimport unittest.mock as mock
19*760c253cSXin Li
20*760c253cSXin Lifrom cros_utils import command_executer
21*760c253cSXin Lifrom cros_utils import logger
22*760c253cSXin Lifrom cros_utils import misc
23*760c253cSXin Liimport image_checksummer
24*760c253cSXin Lifrom label import MockLabel
25*760c253cSXin Liimport machine_manager
26*760c253cSXin Lifrom results_cache import CacheConditions
27*760c253cSXin Lifrom results_cache import PerfDataReadError
28*760c253cSXin Lifrom results_cache import PidVerificationError
29*760c253cSXin Lifrom results_cache import Result
30*760c253cSXin Lifrom results_cache import ResultsCache
31*760c253cSXin Lifrom results_cache import TelemetryResult
32*760c253cSXin Liimport test_flag
33*760c253cSXin Li
34*760c253cSXin Li
35*760c253cSXin Li# The following hardcoded string has blocked words replaced, and thus
36*760c253cSXin Li# is not representative of a true crosperf output.
37*760c253cSXin Li# pylint: disable=line-too-long
38*760c253cSXin LiOUTPUT = """CMD (True): ./test_that.sh\
39*760c253cSXin Li --remote=172.17.128.241  --board=lumpy   LibCBench
40*760c253cSXin LiCMD (None): cd /usr/local/google/home/yunlian/gd/src/build/images/lumpy/latest/../../../../..; cros_sdk  -- ./in_chroot_cmd6X7Cxu.sh
41*760c253cSXin LiIdentity added: /tmp/test_that.PO1234567/autotest_key (/tmp/test_that.PO1234567/autotest_key)
42*760c253cSXin LiINFO    : Using emerged autotests already installed at /build/lumpy/usr/local/autotest.
43*760c253cSXin Li
44*760c253cSXin LiINFO    : Running the following control files 1 times:
45*760c253cSXin LiINFO    :  * 'client/site_tests/platform_LibCBench/control'
46*760c253cSXin Li
47*760c253cSXin LiINFO    : Running client test client/site_tests/platform_LibCBench/control
48*760c253cSXin Li./server/autoserv -m 172.17.128.241 --ssh-port 22 -c client/site_tests/platform_LibCBench/control -r /tmp/test_that.PO1234567/platform_LibCBench --test-retry=0 --args
49*760c253cSXin LiERROR:root:import statsd failed, no stats will be reported.
50*760c253cSXin Li14:20:22 INFO | Results placed in /tmp/test_that.PO1234567/platform_LibCBench
51*760c253cSXin Li14:20:22 INFO | Processing control file
52*760c253cSXin Li14:20:23 INFO | Starting main ssh connection '/usr/bin/ssh -a -x -N -o ControlMain=yes -o ControlPath=/tmp/_autotmp_VIIP67ssh-main/socket -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes -o ConnectTimeout=30 -o ServerAliveInterval=180 -o ServerAliveCountMax=3 -o ConnectionAttempts=4 -o Protocol=2 -l root -p 22 172.17.128.241'
53*760c253cSXin Li14:20:23 ERROR| [stderr] Warning: Permanently added '172.17.128.241' (RSA) to the list of known hosts.
54*760c253cSXin Li14:20:23 INFO | INFO\t----\t----\tkernel=3.8.11\tlocaltime=May 22 14:20:23\ttimestamp=1369257623
55*760c253cSXin Li14:20:23 INFO | Installing autotest on 172.17.128.241
56*760c253cSXin Li14:20:23 INFO | Using installation dir /usr/local/autotest
57*760c253cSXin Li14:20:23 WARNI| No job_repo_url for <remote host: 172.17.128.241>
58*760c253cSXin Li14:20:23 INFO | Could not install autotest using the packaging system: No repos to install an autotest client from. Trying other methods
59*760c253cSXin Li14:20:23 INFO | Installation of autotest completed
60*760c253cSXin Li14:20:24 WARNI| No job_repo_url for <remote host: 172.17.128.241>
61*760c253cSXin Li14:20:24 INFO | Executing /usr/local/autotest/bin/autotest /usr/local/autotest/control phase 0
62*760c253cSXin Li14:20:24 INFO | Entered autotestd_monitor.
63*760c253cSXin Li14:20:24 INFO | Finished launching tail subprocesses.
64*760c253cSXin Li14:20:24 INFO | Finished waiting on autotestd to start.
65*760c253cSXin Li14:20:26 INFO | START\t----\t----\ttimestamp=1369257625\tlocaltime=May 22 14:20:25
66*760c253cSXin Li14:20:26 INFO | \tSTART\tplatform_LibCBench\tplatform_LibCBench\ttimestamp=1369257625\tlocaltime=May 22 14:20:25
67*760c253cSXin Li14:20:30 INFO | \t\tGOOD\tplatform_LibCBench\tplatform_LibCBench\ttimestamp=1369257630\tlocaltime=May 22 14:20:30\tcompleted successfully
68*760c253cSXin Li14:20:30 INFO | \tEND GOOD\tplatform_LibCBench\tplatform_LibCBench\ttimestamp=1369257630\tlocaltime=May 22 14:20:30
69*760c253cSXin Li14:20:31 INFO | END GOOD\t----\t----\ttimestamp=1369257630\tlocaltime=May 22 14:20:30
70*760c253cSXin Li14:20:31 INFO | Got lock of exit_code_file.
71*760c253cSXin Li14:20:31 INFO | Released lock of exit_code_file and closed it.
72*760c253cSXin LiOUTPUT: ==============================
73*760c253cSXin LiOUTPUT: Current time: 2013-05-22 14:20:32.818831 Elapsed: 0:01:30 ETA: Unknown
74*760c253cSXin LiDone: 0% [                                                  ]
75*760c253cSXin LiOUTPUT: Thread Status:
76*760c253cSXin LiRUNNING:  1 ('ttt: LibCBench (1)' 0:01:21)
77*760c253cSXin LiMachine Status:
78*760c253cSXin LiMachine                        Thread     Lock Status                    Checksum
79*760c253cSXin Li172.17.128.241                 ttt: LibCBench (1) True RUNNING                   3ba9f2ecbb222f20887daea5583d86ba
80*760c253cSXin Li
81*760c253cSXin LiOUTPUT: ==============================
82*760c253cSXin Li14:20:33 INFO | Killing child processes.
83*760c253cSXin Li14:20:33 INFO | Client complete
84*760c253cSXin Li14:20:33 INFO | Finished processing control file
85*760c253cSXin Li14:20:33 INFO | Starting main ssh connection '/usr/bin/ssh -a -x -N -o ControlMain=yes -o ControlPath=/tmp/_autotmp_aVJUgmssh-main/socket -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes -o ConnectTimeout=30 -o ServerAliveInterval=180 -o ServerAliveCountMax=3 -o ConnectionAttempts=4 -o Protocol=2 -l root -p 22 172.17.128.241'
86*760c253cSXin Li14:20:33 ERROR| [stderr] Warning: Permanently added '172.17.128.241' (RSA) to the list of known hosts.
87*760c253cSXin Li
88*760c253cSXin LiINFO    : Test results:
89*760c253cSXin Li-------------------------------------------------------------------
90*760c253cSXin Liplatform_LibCBench                                      [  PASSED  ]
91*760c253cSXin Liplatform_LibCBench/platform_LibCBench                   [  PASSED  ]
92*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_malloc_big1__0_                                     0.00375231466667
93*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_malloc_big2__0_                                     0.002951359
94*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_malloc_bubble__0_                                   0.015066374
95*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_malloc_sparse__0_                                   0.015053784
96*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_malloc_thread_local__0_                             0.01138439
97*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_malloc_thread_stress__0_                            0.0367894733333
98*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_malloc_tiny1__0_                                    0.000768474333333
99*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_malloc_tiny2__0_                                    0.000581407333333
100*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_pthread_create_serial1__0_                          0.0291785246667
101*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_pthread_createjoin_serial1__0_                      0.031907936
102*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_pthread_createjoin_serial2__0_                      0.043485347
103*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_pthread_uselesslock__0_                             0.0294113346667
104*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_regex_compile____a_b_c__d_b__                       0.00529833933333
105*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_regex_search____a_b_c__d_b__                        0.00165455066667
106*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_regex_search___a_25_b__                             0.0496191923333
107*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_stdio_putcgetc__0_                                  0.100005711667
108*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_stdio_putcgetc_unlocked__0_                         0.0371443833333
109*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_string_memset__0_                                   0.00275405066667
110*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_string_strchr__0_                                   0.00456903
111*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_string_strlen__0_                                   0.044893587
112*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_string_strstr___aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac__ 0.118360778
113*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_string_strstr___aaaaaaaaaaaaaaaaaaaaaaaaac__        0.068957325
114*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_string_strstr___aaaaaaaaaaaaaacccccccccccc__        0.0135694476667
115*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_string_strstr___abcdefghijklmnopqrstuvwxyz__        0.0134553343333
116*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_string_strstr___azbycxdwevfugthsirjqkplomn__        0.0133123556667
117*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_utf8_bigbuf__0_                                     0.0473772253333
118*760c253cSXin Liplatform_LibCBench/platform_LibCBench                     b_utf8_onebyone__0_                                   0.130938538333
119*760c253cSXin Li-------------------------------------------------------------------
120*760c253cSXin LiTotal PASS: 2/2 (100%)
121*760c253cSXin Li
122*760c253cSXin LiINFO    : Elapsed time: 0m16s
123*760c253cSXin Li"""
124*760c253cSXin Li
125*760c253cSXin Lierror = """
126*760c253cSXin LiERROR: Identity added: /tmp/test_that.Z4Ld/autotest_key (/tmp/test_that.Z4Ld/autotest_key)
127*760c253cSXin LiINFO    : Using emerged autotests already installed at /build/lumpy/usr/local/autotest.
128*760c253cSXin LiINFO    : Running the following control files 1 times:
129*760c253cSXin LiINFO    :  * 'client/site_tests/platform_LibCBench/control'
130*760c253cSXin LiINFO    : Running client test client/site_tests/platform_LibCBench/control
131*760c253cSXin LiINFO    : Test results:
132*760c253cSXin LiINFO    : Elapsed time: 0m18s
133*760c253cSXin Li"""
134*760c253cSXin Li
135*760c253cSXin Likeyvals = {
136*760c253cSXin Li    "": "PASS",
137*760c253cSXin Li    "b_stdio_putcgetc__0_": "0.100005711667",
138*760c253cSXin Li    "b_string_strstr___azbycxdwevfugthsirjqkplomn__": "0.0133123556667",
139*760c253cSXin Li    "b_malloc_thread_local__0_": "0.01138439",
140*760c253cSXin Li    "b_string_strlen__0_": "0.044893587",
141*760c253cSXin Li    "b_malloc_sparse__0_": "0.015053784",
142*760c253cSXin Li    "b_string_memset__0_": "0.00275405066667",
143*760c253cSXin Li    "platform_LibCBench": "PASS",
144*760c253cSXin Li    "b_pthread_uselesslock__0_": "0.0294113346667",
145*760c253cSXin Li    "b_string_strchr__0_": "0.00456903",
146*760c253cSXin Li    "b_pthread_create_serial1__0_": "0.0291785246667",
147*760c253cSXin Li    "b_string_strstr___aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac__": "0.118360778",
148*760c253cSXin Li    "b_string_strstr___aaaaaaaaaaaaaacccccccccccc__": "0.0135694476667",
149*760c253cSXin Li    "b_pthread_createjoin_serial1__0_": "0.031907936",
150*760c253cSXin Li    "b_malloc_thread_stress__0_": "0.0367894733333",
151*760c253cSXin Li    "b_regex_search____a_b_c__d_b__": "0.00165455066667",
152*760c253cSXin Li    "b_malloc_bubble__0_": "0.015066374",
153*760c253cSXin Li    "b_malloc_big2__0_": "0.002951359",
154*760c253cSXin Li    "b_stdio_putcgetc_unlocked__0_": "0.0371443833333",
155*760c253cSXin Li    "b_pthread_createjoin_serial2__0_": "0.043485347",
156*760c253cSXin Li    "b_regex_search___a_25_b__": "0.0496191923333",
157*760c253cSXin Li    "b_utf8_bigbuf__0_": "0.0473772253333",
158*760c253cSXin Li    "b_malloc_big1__0_": "0.00375231466667",
159*760c253cSXin Li    "b_regex_compile____a_b_c__d_b__": "0.00529833933333",
160*760c253cSXin Li    "b_string_strstr___aaaaaaaaaaaaaaaaaaaaaaaaac__": "0.068957325",
161*760c253cSXin Li    "b_malloc_tiny2__0_": "0.000581407333333",
162*760c253cSXin Li    "b_utf8_onebyone__0_": "0.130938538333",
163*760c253cSXin Li    "b_malloc_tiny1__0_": "0.000768474333333",
164*760c253cSXin Li    "b_string_strstr___abcdefghijklmnopqrstuvwxyz__": "0.0134553343333",
165*760c253cSXin Li}
166*760c253cSXin Li
167*760c253cSXin LiPERF_DATA_HEADER = """
168*760c253cSXin Li# ========
169*760c253cSXin Li# captured on    : Thu Jan 01 00:00:00 1980
170*760c253cSXin Li# header version : 1
171*760c253cSXin Li# data offset    : 536
172*760c253cSXin Li# data size      : 737678672
173*760c253cSXin Li# feat offset    : 737679208
174*760c253cSXin Li# hostname : localhost
175*760c253cSXin Li# os release : 5.4.61
176*760c253cSXin Li# perf version :
177*760c253cSXin Li# arch : aarch64
178*760c253cSXin Li# nrcpus online : 8
179*760c253cSXin Li# nrcpus avail : 8
180*760c253cSXin Li# total memory : 5911496 kB
181*760c253cSXin Li# cmdline : /usr/bin/perf record -e instructions -p {pid}
182*760c253cSXin Li# event : name = instructions, , id = ( 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193 ), type = 8, size = 112
183*760c253cSXin Li# event : name = placeholder:u, , id = ( 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204 ), type = 1, size = 112, config = 0x9
184*760c253cSXin Li# CPU_TOPOLOGY info available, use -I to display
185*760c253cSXin Li# pmu mappings: software = 1, uprobe = 6, cs_etm = 8, breakpoint = 5, tracepoint = 2, armv8_pmuv3 = 7
186*760c253cSXin Li# contains AUX area data (e.g. instruction trace)
187*760c253cSXin Li# time of first sample : 0.000000
188*760c253cSXin Li# time of last sample : 0.000000
189*760c253cSXin Li# sample duration :      0.000 ms
190*760c253cSXin Li# missing features: TRACING_DATA CPUDESC CPUID NUMA_TOPOLOGY BRANCH_STACK GROUP_DESC STAT CACHE MEM_TOPOLOGY CLOCKID DIR_FORMAT
191*760c253cSXin Li# ========
192*760c253cSXin Li#
193*760c253cSXin Li"""
194*760c253cSXin Li
195*760c253cSXin LiTURBOSTAT_LOG_OUTPUT = """CPU     Avg_MHz Busy%   Bzy_MHz TSC_MHz IRQ     CoreTmp
196*760c253cSXin Li-       329     12.13   2723    2393    10975   77
197*760c253cSXin Li0       336     12.41   2715    2393    6328    77
198*760c253cSXin Li2       323     11.86   2731    2393    4647    69
199*760c253cSXin LiCPU     Avg_MHz Busy%   Bzy_MHz TSC_MHz IRQ     CoreTmp
200*760c253cSXin Li-       1940    67.46   2884    2393    39920   83
201*760c253cSXin Li0       1827    63.70   2877    2393    21184   83
202*760c253cSXin Li2       2053    71.22   2891    2393    18736   67
203*760c253cSXin LiCPU     Avg_MHz Busy%   Bzy_MHz TSC_MHz IRQ     CoreTmp
204*760c253cSXin Li-       1927    66.02   2927    2393    48946   84
205*760c253cSXin Li0       1880    64.47   2925    2393    24457   84
206*760c253cSXin Li2       1973    67.57   2928    2393    24489   69
207*760c253cSXin LiCPU     Avg_MHz Busy%   Bzy_MHz TSC_MHz IRQ     CoreTmp
208*760c253cSXin Li-       1899    64.84   2937    2393    42540   72
209*760c253cSXin Li0       2135    72.82   2940    2393    23615   65
210*760c253cSXin Li2       1663    56.85   2934    2393    18925   72
211*760c253cSXin LiCPU     Avg_MHz Busy%   Bzy_MHz TSC_MHz IRQ     CoreTmp
212*760c253cSXin Li-       1908    65.24   2932    2393    43172   75
213*760c253cSXin Li0       1876    64.25   2928    2393    20743   75
214*760c253cSXin Li2       1939    66.24   2936    2393    22429   69
215*760c253cSXin LiCPU     Avg_MHz Busy%   Bzy_MHz TSC_MHz IRQ     CoreTmp
216*760c253cSXin Li-       1553    53.12   2933    2393    35488   46
217*760c253cSXin Li0       1484    50.80   2929    2393    18246   46
218*760c253cSXin Li2       1623    55.44   2936    2393    17242   45
219*760c253cSXin LiCPU     Avg_MHz Busy%   Bzy_MHz TSC_MHz IRQ     CoreTmp
220*760c253cSXin Li-       843     29.83   2832    2393    28161   47
221*760c253cSXin Li0       827     29.35   2826    2393    16093   47
222*760c253cSXin Li2       858     30.31   2838    2393    12068   46
223*760c253cSXin Li"""
224*760c253cSXin LiTURBOSTAT_DATA = {
225*760c253cSXin Li    "cpufreq": {"all": [2723, 2884, 2927, 2937, 2932, 2933, 2832]},
226*760c253cSXin Li    "cputemp": {"all": [77, 83, 84, 72, 75, 46, 47]},
227*760c253cSXin Li}
228*760c253cSXin Li
229*760c253cSXin LiTOP_LOG = """
230*760c253cSXin Li  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
231*760c253cSXin Li 4102 chronos   12  -8 3454472 238300 118188 R  41.8   6.1   0:08.37 chrome
232*760c253cSXin Li 4204 chronos   12  -8 2492716 205728 179016 S  11.8   5.3   0:03.89 chrome
233*760c253cSXin Li 4890 root      20   0    3396   2064   1596 R  11.8   0.1   0:00.03 top
234*760c253cSXin Li  375 root       0 -20       0      0      0 S   5.9   0.0   0:00.17 kworker/u13
235*760c253cSXin Li  617 syslog    20   0   25332   8372   7888 S   5.9   0.2   0:00.77 sys-journal
236*760c253cSXin Li
237*760c253cSXin Li  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
238*760c253cSXin Li 5745 chronos   20   0 5438580 139328  67988 R 122.8   3.6   0:04.26 chrome
239*760c253cSXin Li  912 root     -51   0       0      0      0 S   2.0   0.0   0:01.04 irq/cros-ec
240*760c253cSXin Li  121 root      20   0       0      0      0 S   1.0   0.0   0:00.45 spi5
241*760c253cSXin Li 4811 root      20   0    6808   4084   3492 S   1.0   0.1   0:00.02 sshd
242*760c253cSXin Li 4890 root      20   0    3364   2148   1596 R   1.0   0.1   0:00.36 top
243*760c253cSXin Li 5205 chronos   12  -8 3673780 240928 130864 S   1.0   6.2   0:07.30 chrome
244*760c253cSXin Li
245*760c253cSXin Li
246*760c253cSXin Li  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
247*760c253cSXin Li 5745 chronos   20   0 5434484 139432  63892 R 107.9   3.6   0:05.35 chrome
248*760c253cSXin Li 5713 chronos   20   0 5178652 103120  50372 S  17.8   2.6   0:01.13 chrome
249*760c253cSXin Li    7 root      20   0       0      0      0 S   1.0   0.0   0:00.73 rcu_preempt
250*760c253cSXin Li  855 root      20   0       0      0      0 S   1.0   0.0   0:00.01 kworker/4:2
251*760c253cSXin Li"""
252*760c253cSXin LiTOP_DATA = [
253*760c253cSXin Li    {
254*760c253cSXin Li        "cmd": "chrome-5745",
255*760c253cSXin Li        "cpu_use_avg": 115.35,
256*760c253cSXin Li        "count": 2,
257*760c253cSXin Li        "top5_cpu_use": [122.8, 107.9],
258*760c253cSXin Li    },
259*760c253cSXin Li    {
260*760c253cSXin Li        "cmd": "chrome-5713",
261*760c253cSXin Li        "cpu_use_avg": 8.9,
262*760c253cSXin Li        "count": 1,
263*760c253cSXin Li        "top5_cpu_use": [17.8],
264*760c253cSXin Li    },
265*760c253cSXin Li    {
266*760c253cSXin Li        "cmd": "irq/cros-ec-912",
267*760c253cSXin Li        "cpu_use_avg": 1.0,
268*760c253cSXin Li        "count": 1,
269*760c253cSXin Li        "top5_cpu_use": [2.0],
270*760c253cSXin Li    },
271*760c253cSXin Li    {
272*760c253cSXin Li        "cmd": "chrome-5205",
273*760c253cSXin Li        "cpu_use_avg": 0.5,
274*760c253cSXin Li        "count": 1,
275*760c253cSXin Li        "top5_cpu_use": [1.0],
276*760c253cSXin Li    },
277*760c253cSXin Li    {
278*760c253cSXin Li        "cmd": "spi5-121",
279*760c253cSXin Li        "cpu_use_avg": 0.5,
280*760c253cSXin Li        "count": 1,
281*760c253cSXin Li        "top5_cpu_use": [1.0],
282*760c253cSXin Li    },
283*760c253cSXin Li    {
284*760c253cSXin Li        "cmd": "sshd-4811",
285*760c253cSXin Li        "cpu_use_avg": 0.5,
286*760c253cSXin Li        "count": 1,
287*760c253cSXin Li        "top5_cpu_use": [1.0],
288*760c253cSXin Li    },
289*760c253cSXin Li    {
290*760c253cSXin Li        "cmd": "rcu_preempt-7",
291*760c253cSXin Li        "cpu_use_avg": 0.5,
292*760c253cSXin Li        "count": 1,
293*760c253cSXin Li        "top5_cpu_use": [1.0],
294*760c253cSXin Li    },
295*760c253cSXin Li    {
296*760c253cSXin Li        "cmd": "kworker/4:2-855",
297*760c253cSXin Li        "cpu_use_avg": 0.5,
298*760c253cSXin Li        "count": 1,
299*760c253cSXin Li        "top5_cpu_use": [1.0],
300*760c253cSXin Li    },
301*760c253cSXin Li]
302*760c253cSXin LiTOP_OUTPUT = """             COMMAND     AVG CPU%  SEEN   HIGHEST 5
303*760c253cSXin Li              chrome   128.250000     6   [122.8, 107.9, 17.8, 5.0, 2.0]
304*760c253cSXin Li     irq/230-cros-ec     1.000000     1   [2.0]
305*760c253cSXin Li                sshd     0.500000     1   [1.0]
306*760c253cSXin Li     irq/231-cros-ec     0.500000     1   [1.0]
307*760c253cSXin Li                spi5     0.500000     1   [1.0]
308*760c253cSXin Li         rcu_preempt     0.500000     1   [1.0]
309*760c253cSXin Li         kworker/4:2     0.500000     1   [1.0]
310*760c253cSXin Li"""
311*760c253cSXin Li
312*760c253cSXin LiCPUSTATS_UNIQ_OUTPUT = """
313*760c253cSXin Li/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq 1512000
314*760c253cSXin Li/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_cur_freq 1512000
315*760c253cSXin Li/sys/devices/system/cpu/cpu3/cpufreq/cpuinfo_cur_freq 2016000
316*760c253cSXin Lisoc-thermal 44444
317*760c253cSXin Lilittle-cpu 41234
318*760c253cSXin Libig-cpu 51234
319*760c253cSXin Li/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq 1500000
320*760c253cSXin Li/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_cur_freq 1600000
321*760c253cSXin Li/sys/devices/system/cpu/cpu3/cpufreq/cpuinfo_cur_freq 2012000
322*760c253cSXin Lisoc-thermal 45456
323*760c253cSXin Lilittle-cpu 42555
324*760c253cSXin Libig-cpu 61724
325*760c253cSXin Li"""
326*760c253cSXin LiCPUSTATS_UNIQ_DATA = {
327*760c253cSXin Li    "cpufreq": {
328*760c253cSXin Li        "cpu0": [1512, 1500],
329*760c253cSXin Li        "cpu1": [1512, 1600],
330*760c253cSXin Li        "cpu3": [2016, 2012],
331*760c253cSXin Li    },
332*760c253cSXin Li    "cputemp": {
333*760c253cSXin Li        "soc-thermal": [44.4, 45.5],
334*760c253cSXin Li        "little-cpu": [41.2, 42.6],
335*760c253cSXin Li        "big-cpu": [51.2, 61.7],
336*760c253cSXin Li    },
337*760c253cSXin Li}
338*760c253cSXin LiCPUSTATS_DUPL_OUTPUT = """
339*760c253cSXin Li/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq 1512000
340*760c253cSXin Li/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_cur_freq 1512000
341*760c253cSXin Li/sys/devices/system/cpu/cpu2/cpufreq/cpuinfo_cur_freq 1512000
342*760c253cSXin Li/sys/devices/system/cpu/cpu3/cpufreq/cpuinfo_cur_freq 2016000
343*760c253cSXin Li/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq 1500000
344*760c253cSXin Li/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_cur_freq 1500000
345*760c253cSXin Li/sys/devices/system/cpu/cpu2/cpufreq/cpuinfo_cur_freq 1500000
346*760c253cSXin Li/sys/devices/system/cpu/cpu3/cpufreq/cpuinfo_cur_freq 2016000
347*760c253cSXin Li/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq 1614000
348*760c253cSXin Li/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_cur_freq 1614000
349*760c253cSXin Li/sys/devices/system/cpu/cpu2/cpufreq/cpuinfo_cur_freq 1614000
350*760c253cSXin Li/sys/devices/system/cpu/cpu3/cpufreq/cpuinfo_cur_freq 1982000
351*760c253cSXin Li"""
352*760c253cSXin LiCPUSTATS_DUPL_DATA = {
353*760c253cSXin Li    "cpufreq": {"cpu0": [1512, 1500, 1614], "cpu3": [2016, 2016, 1982]},
354*760c253cSXin Li}
355*760c253cSXin Li
356*760c253cSXin LiTMP_DIR1 = "/tmp/tmpAbcXyz"
357*760c253cSXin Li
358*760c253cSXin LiHISTOGRAMSET = """
359*760c253cSXin Li[
360*760c253cSXin Li    {
361*760c253cSXin Li        "values": [
362*760c253cSXin Li            "cache_temperature_cold",
363*760c253cSXin Li            "typical",
364*760c253cSXin Li            "cache_temperature:cold"
365*760c253cSXin Li        ],
366*760c253cSXin Li        "guid": "db6d463b-7c07-4873-b839-db0652ccb97e",
367*760c253cSXin Li        "type": "GenericSet"
368*760c253cSXin Li    },
369*760c253cSXin Li    {
370*760c253cSXin Li        "values": [
371*760c253cSXin Li            "cache_temperature_warm",
372*760c253cSXin Li            "typical",
373*760c253cSXin Li            "cache_temperature:warm"
374*760c253cSXin Li        ],
375*760c253cSXin Li        "guid": "a270eb9d-3bb0-472a-951d-74ac3398b718",
376*760c253cSXin Li        "type": "GenericSet"
377*760c253cSXin Li    },
378*760c253cSXin Li    {
379*760c253cSXin Li        "sampleValues": [
380*760c253cSXin Li            1111.672
381*760c253cSXin Li        ],
382*760c253cSXin Li        "name": "timeToFirstContentfulPaint",
383*760c253cSXin Li        "diagnostics": {
384*760c253cSXin Li            "storyTags": "a270eb9d-3bb0-472a-951d-74ac3398b718"
385*760c253cSXin Li        },
386*760c253cSXin Li        "unit": "ms_smallerIsBetter"
387*760c253cSXin Li    },
388*760c253cSXin Li    {
389*760c253cSXin Li        "sampleValues": [
390*760c253cSXin Li            1146.459
391*760c253cSXin Li        ],
392*760c253cSXin Li        "name": "timeToFirstContentfulPaint",
393*760c253cSXin Li        "diagnostics": {
394*760c253cSXin Li            "storyTags": "db6d463b-7c07-4873-b839-db0652ccb97e"
395*760c253cSXin Li        },
396*760c253cSXin Li        "unit": "ms_smallerIsBetter"
397*760c253cSXin Li    },
398*760c253cSXin Li    {
399*760c253cSXin Li        "sampleValues": [
400*760c253cSXin Li            888.328
401*760c253cSXin Li        ],
402*760c253cSXin Li        "name": "timeToFirstContentfulPaint",
403*760c253cSXin Li        "diagnostics": {
404*760c253cSXin Li            "storyTags": "a270eb9d-3bb0-472a-951d-74ac3398b718"
405*760c253cSXin Li        },
406*760c253cSXin Li        "unit": "ms_smallerIsBetter"
407*760c253cSXin Li    },
408*760c253cSXin Li    {
409*760c253cSXin Li        "sampleValues": [
410*760c253cSXin Li            853.541
411*760c253cSXin Li        ],
412*760c253cSXin Li        "name": "timeToFirstContentfulPaint",
413*760c253cSXin Li        "diagnostics": {
414*760c253cSXin Li            "storyTags": "db6d463b-7c07-4873-b839-db0652ccb97e"
415*760c253cSXin Li        },
416*760c253cSXin Li        "unit": "ms_smallerIsBetter"
417*760c253cSXin Li    },
418*760c253cSXin Li    {
419*760c253cSXin Li        "sampleValues": [
420*760c253cSXin Li            400.000
421*760c253cSXin Li        ],
422*760c253cSXin Li        "name": "timeToFirstContentfulPaint",
423*760c253cSXin Li        "diagnostics": {
424*760c253cSXin Li            "storyTags": "a270eb9d-3bb0-472a-951d-74ac3398b718"
425*760c253cSXin Li        },
426*760c253cSXin Li        "unit": "ms_smallerIsBetter"
427*760c253cSXin Li    }
428*760c253cSXin Li
429*760c253cSXin Li]
430*760c253cSXin Li"""
431*760c253cSXin Li
432*760c253cSXin Li# pylint: enable=line-too-long
433*760c253cSXin Li
434*760c253cSXin Li
435*760c253cSXin Liclass MockResult(Result):
436*760c253cSXin Li    """Mock result class."""
437*760c253cSXin Li
438*760c253cSXin Li    def __init__(self, mylogger, label, logging_level, machine):
439*760c253cSXin Li        super(MockResult, self).__init__(
440*760c253cSXin Li            mylogger, label, logging_level, machine
441*760c253cSXin Li        )
442*760c253cSXin Li
443*760c253cSXin Li    def FindFilesInResultsDir(self, find_args):
444*760c253cSXin Li        return ""
445*760c253cSXin Li
446*760c253cSXin Li    # pylint: disable=arguments-differ
447*760c253cSXin Li    def GetKeyvals(self, temp=False):
448*760c253cSXin Li        if temp:
449*760c253cSXin Li            pass
450*760c253cSXin Li        return keyvals
451*760c253cSXin Li
452*760c253cSXin Li
453*760c253cSXin Liclass RegexMatcher:
454*760c253cSXin Li    """A regex matcher, for passing to mocks."""
455*760c253cSXin Li
456*760c253cSXin Li    def __init__(self, regex):
457*760c253cSXin Li        self._regex = re.compile(regex)
458*760c253cSXin Li
459*760c253cSXin Li    def __eq__(self, string):
460*760c253cSXin Li        return self._regex.search(string) is not None
461*760c253cSXin Li
462*760c253cSXin Li
463*760c253cSXin Liclass ResultTest(unittest.TestCase):
464*760c253cSXin Li    """Result test class."""
465*760c253cSXin Li
466*760c253cSXin Li    def __init__(self, *args, **kwargs):
467*760c253cSXin Li        super(ResultTest, self).__init__(*args, **kwargs)
468*760c253cSXin Li        self.callFakeProcessResults = False
469*760c253cSXin Li        self.fakeCacheReturnResult = None
470*760c253cSXin Li        self.callGetResultsDir = False
471*760c253cSXin Li        self.callProcessResults = False
472*760c253cSXin Li        self.callGetPerfReportFiles = False
473*760c253cSXin Li        self.kv_dict = None
474*760c253cSXin Li        self.tmpdir = ""
475*760c253cSXin Li        self.callGetNewKeyvals = False
476*760c253cSXin Li        self.callGetResultsFile = False
477*760c253cSXin Li        self.callGetPerfDataFiles = False
478*760c253cSXin Li        self.callGetTurbostatFile = False
479*760c253cSXin Li        self.callGetCpustatsFile = False
480*760c253cSXin Li        self.callGetTopFile = False
481*760c253cSXin Li        self.callGetCpuinfoFile = False
482*760c253cSXin Li        self.callGetWaitTimeFile = False
483*760c253cSXin Li        self.args = None
484*760c253cSXin Li        self.callGatherPerfResults = False
485*760c253cSXin Li        self.mock_logger = mock.Mock(spec=logger.Logger)
486*760c253cSXin Li        self.mock_cmd_exec = mock.Mock(spec=command_executer.CommandExecuter)
487*760c253cSXin Li        self.mock_label = MockLabel(
488*760c253cSXin Li            "mock_label",
489*760c253cSXin Li            "build",
490*760c253cSXin Li            "chromeos_image",
491*760c253cSXin Li            "autotest_dir",
492*760c253cSXin Li            "debug_dir",
493*760c253cSXin Li            "/tmp",
494*760c253cSXin Li            "lumpy",
495*760c253cSXin Li            "remote",
496*760c253cSXin Li            "image_args",
497*760c253cSXin Li            "cache_dir",
498*760c253cSXin Li            "average",
499*760c253cSXin Li            "gcc",
500*760c253cSXin Li            False,
501*760c253cSXin Li            None,
502*760c253cSXin Li        )
503*760c253cSXin Li
504*760c253cSXin Li    @mock.patch.object(os.path, "exists")
505*760c253cSXin Li    def testCreateFromRun(self, mock_path_exists):
506*760c253cSXin Li        mock_path_exists.side_effect = lambda x: x != "/etc/cros_chroot_version"
507*760c253cSXin Li        result = MockResult.CreateFromRun(
508*760c253cSXin Li            logger.GetLogger(),
509*760c253cSXin Li            "average",
510*760c253cSXin Li            self.mock_label,
511*760c253cSXin Li            "remote1",
512*760c253cSXin Li            OUTPUT,
513*760c253cSXin Li            error,
514*760c253cSXin Li            0,
515*760c253cSXin Li            True,
516*760c253cSXin Li        )
517*760c253cSXin Li        self.assertEqual(result.keyvals, keyvals)
518*760c253cSXin Li        self.assertEqual(
519*760c253cSXin Li            result.chroot_results_dir,
520*760c253cSXin Li            "/tmp/test_that.PO1234567/platform_LibCBench",
521*760c253cSXin Li        )
522*760c253cSXin Li        self.assertEqual(
523*760c253cSXin Li            result.results_dir,
524*760c253cSXin Li            RegexMatcher("/tmp/.*tmp/test_that.PO1234567/platform_LibCBench"),
525*760c253cSXin Li        )
526*760c253cSXin Li        self.assertEqual(result.retval, 0)
527*760c253cSXin Li
528*760c253cSXin Li    def setUp(self):
529*760c253cSXin Li        self.result = Result(
530*760c253cSXin Li            self.mock_logger, self.mock_label, "average", self.mock_cmd_exec
531*760c253cSXin Li        )
532*760c253cSXin Li        self.result.chromeos_root = "/tmp/chromeos"
533*760c253cSXin Li        self.orig_exists = os.path.exists
534*760c253cSXin Li
535*760c253cSXin Li    @mock.patch.object(os.path, "isdir")
536*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommand")
537*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "CopyFiles")
538*760c253cSXin Li    def test_copy_files_to(self, mock_copyfiles, mock_runcmd, mock_isdir):
539*760c253cSXin Li        files = ["src_file_1", "src_file_2", "src_file_3"]
540*760c253cSXin Li        dest_dir = "/tmp/test"
541*760c253cSXin Li        self.mock_cmd_exec.RunCommand = mock_runcmd
542*760c253cSXin Li        self.mock_cmd_exec.CopyFiles = mock_copyfiles
543*760c253cSXin Li
544*760c253cSXin Li        mock_copyfiles.return_value = 0
545*760c253cSXin Li
546*760c253cSXin Li        # test 1. dest_dir exists; CopyFiles returns 0.
547*760c253cSXin Li        mock_isdir.return_value = True
548*760c253cSXin Li        self.result.CopyFilesTo(dest_dir, files)
549*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 0)
550*760c253cSXin Li        self.assertEqual(mock_copyfiles.call_count, 3)
551*760c253cSXin Li        first_args = mock_copyfiles.call_args_list[0][0]
552*760c253cSXin Li        second_args = mock_copyfiles.call_args_list[1][0]
553*760c253cSXin Li        third_args = mock_copyfiles.call_args_list[2][0]
554*760c253cSXin Li        self.assertEqual(first_args, ("src_file_1", "/tmp/test/src_file_1.0"))
555*760c253cSXin Li        self.assertEqual(second_args, ("src_file_2", "/tmp/test/src_file_2.1"))
556*760c253cSXin Li        self.assertEqual(third_args, ("src_file_3", "/tmp/test/src_file_3.2"))
557*760c253cSXin Li
558*760c253cSXin Li        mock_runcmd.reset_mock()
559*760c253cSXin Li        mock_copyfiles.reset_mock()
560*760c253cSXin Li        # test 2. dest_dir does not exist; CopyFiles returns 0.
561*760c253cSXin Li        mock_isdir.return_value = False
562*760c253cSXin Li        self.result.CopyFilesTo(dest_dir, files)
563*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 3)
564*760c253cSXin Li        self.assertEqual(mock_copyfiles.call_count, 3)
565*760c253cSXin Li        self.assertEqual(
566*760c253cSXin Li            mock_runcmd.call_args_list[0], mock_runcmd.call_args_list[1]
567*760c253cSXin Li        )
568*760c253cSXin Li        self.assertEqual(
569*760c253cSXin Li            mock_runcmd.call_args_list[0], mock_runcmd.call_args_list[2]
570*760c253cSXin Li        )
571*760c253cSXin Li        self.assertEqual(
572*760c253cSXin Li            mock_runcmd.call_args_list[0][0], ("mkdir -p /tmp/test",)
573*760c253cSXin Li        )
574*760c253cSXin Li
575*760c253cSXin Li        # test 3. CopyFiles returns 1 (fails).
576*760c253cSXin Li        mock_copyfiles.return_value = 1
577*760c253cSXin Li        self.assertRaises(Exception, self.result.CopyFilesTo, dest_dir, files)
578*760c253cSXin Li
579*760c253cSXin Li    @mock.patch.object(Result, "CopyFilesTo")
580*760c253cSXin Li    def test_copy_results_to(self, mockCopyFilesTo):
581*760c253cSXin Li        results_file = [
582*760c253cSXin Li            "/tmp/result.json.0",
583*760c253cSXin Li            "/tmp/result.json.1",
584*760c253cSXin Li            "/tmp/result.json.2",
585*760c253cSXin Li        ]
586*760c253cSXin Li        perf_data_files = [
587*760c253cSXin Li            "/tmp/perf.data.0",
588*760c253cSXin Li            "/tmp/perf.data.1",
589*760c253cSXin Li            "/tmp/perf.data.2",
590*760c253cSXin Li        ]
591*760c253cSXin Li        perf_report_files = [
592*760c253cSXin Li            "/tmp/perf.report.0",
593*760c253cSXin Li            "/tmp/perf.report.1",
594*760c253cSXin Li            "/tmp/perf.report.2",
595*760c253cSXin Li        ]
596*760c253cSXin Li
597*760c253cSXin Li        self.result.results_file = results_file
598*760c253cSXin Li        self.result.perf_data_files = perf_data_files
599*760c253cSXin Li        self.result.perf_report_files = perf_report_files
600*760c253cSXin Li
601*760c253cSXin Li        self.result.CopyFilesTo = mockCopyFilesTo
602*760c253cSXin Li        self.result.CopyResultsTo("/tmp/results/")
603*760c253cSXin Li        self.assertEqual(mockCopyFilesTo.call_count, 3)
604*760c253cSXin Li        self.assertEqual(len(mockCopyFilesTo.call_args_list), 3)
605*760c253cSXin Li        self.assertEqual(
606*760c253cSXin Li            mockCopyFilesTo.call_args_list[0][0],
607*760c253cSXin Li            ("/tmp/results/", results_file),
608*760c253cSXin Li        )
609*760c253cSXin Li        self.assertEqual(
610*760c253cSXin Li            mockCopyFilesTo.call_args_list[1][0],
611*760c253cSXin Li            ("/tmp/results/", perf_data_files),
612*760c253cSXin Li        )
613*760c253cSXin Li        self.assertEqual(
614*760c253cSXin Li            mockCopyFilesTo.call_args_list[2][0],
615*760c253cSXin Li            ("/tmp/results/", perf_report_files),
616*760c253cSXin Li        )
617*760c253cSXin Li
618*760c253cSXin Li    def test_get_new_keyvals(self):
619*760c253cSXin Li        kv_dict = {}
620*760c253cSXin Li
621*760c253cSXin Li        def FakeGetDataMeasurementsFiles():
622*760c253cSXin Li            filename = os.path.join(os.getcwd(), "unittest_keyval_file.txt")
623*760c253cSXin Li            return [filename]
624*760c253cSXin Li
625*760c253cSXin Li        self.result.GetDataMeasurementsFiles = FakeGetDataMeasurementsFiles
626*760c253cSXin Li        kv_dict2, udict = self.result.GetNewKeyvals(kv_dict)
627*760c253cSXin Li        self.assertEqual(
628*760c253cSXin Li            kv_dict2,
629*760c253cSXin Li            {
630*760c253cSXin Li                "Box2D__Box2D": 4775,
631*760c253cSXin Li                "Mandreel__Mandreel": 6620,
632*760c253cSXin Li                "Gameboy__Gameboy": 9901,
633*760c253cSXin Li                "Crypto__Crypto": 8737,
634*760c253cSXin Li                "telemetry_page_measurement_results__num_errored": 0,
635*760c253cSXin Li                "telemetry_page_measurement_results__num_failed": 0,
636*760c253cSXin Li                "PdfJS__PdfJS": 6455,
637*760c253cSXin Li                "Total__Score": 7918,
638*760c253cSXin Li                "EarleyBoyer__EarleyBoyer": 14340,
639*760c253cSXin Li                "MandreelLatency__MandreelLatency": 5188,
640*760c253cSXin Li                "CodeLoad__CodeLoad": 6271,
641*760c253cSXin Li                "DeltaBlue__DeltaBlue": 14401,
642*760c253cSXin Li                "Typescript__Typescript": 9815,
643*760c253cSXin Li                "SplayLatency__SplayLatency": 7653,
644*760c253cSXin Li                "zlib__zlib": 16094,
645*760c253cSXin Li                "Richards__Richards": 10358,
646*760c253cSXin Li                "RegExp__RegExp": 1765,
647*760c253cSXin Li                "NavierStokes__NavierStokes": 9815,
648*760c253cSXin Li                "Splay__Splay": 4425,
649*760c253cSXin Li                "RayTrace__RayTrace": 16600,
650*760c253cSXin Li            },
651*760c253cSXin Li        )
652*760c253cSXin Li        self.assertEqual(
653*760c253cSXin Li            udict,
654*760c253cSXin Li            {
655*760c253cSXin Li                "Box2D__Box2D": "score",
656*760c253cSXin Li                "Mandreel__Mandreel": "score",
657*760c253cSXin Li                "Gameboy__Gameboy": "score",
658*760c253cSXin Li                "Crypto__Crypto": "score",
659*760c253cSXin Li                "telemetry_page_measurement_results__num_errored": "count",
660*760c253cSXin Li                "telemetry_page_measurement_results__num_failed": "count",
661*760c253cSXin Li                "PdfJS__PdfJS": "score",
662*760c253cSXin Li                "Total__Score": "score",
663*760c253cSXin Li                "EarleyBoyer__EarleyBoyer": "score",
664*760c253cSXin Li                "MandreelLatency__MandreelLatency": "score",
665*760c253cSXin Li                "CodeLoad__CodeLoad": "score",
666*760c253cSXin Li                "DeltaBlue__DeltaBlue": "score",
667*760c253cSXin Li                "Typescript__Typescript": "score",
668*760c253cSXin Li                "SplayLatency__SplayLatency": "score",
669*760c253cSXin Li                "zlib__zlib": "score",
670*760c253cSXin Li                "Richards__Richards": "score",
671*760c253cSXin Li                "RegExp__RegExp": "score",
672*760c253cSXin Li                "NavierStokes__NavierStokes": "score",
673*760c253cSXin Li                "Splay__Splay": "score",
674*760c253cSXin Li                "RayTrace__RayTrace": "score",
675*760c253cSXin Li            },
676*760c253cSXin Li        )
677*760c253cSXin Li
678*760c253cSXin Li    def test_append_telemetry_units(self):
679*760c253cSXin Li        kv_dict = {
680*760c253cSXin Li            "Box2D__Box2D": 4775,
681*760c253cSXin Li            "Mandreel__Mandreel": 6620,
682*760c253cSXin Li            "Gameboy__Gameboy": 9901,
683*760c253cSXin Li            "Crypto__Crypto": 8737,
684*760c253cSXin Li            "PdfJS__PdfJS": 6455,
685*760c253cSXin Li            "Total__Score": 7918,
686*760c253cSXin Li            "EarleyBoyer__EarleyBoyer": 14340,
687*760c253cSXin Li            "MandreelLatency__MandreelLatency": 5188,
688*760c253cSXin Li            "CodeLoad__CodeLoad": 6271,
689*760c253cSXin Li            "DeltaBlue__DeltaBlue": 14401,
690*760c253cSXin Li            "Typescript__Typescript": 9815,
691*760c253cSXin Li            "SplayLatency__SplayLatency": 7653,
692*760c253cSXin Li            "zlib__zlib": 16094,
693*760c253cSXin Li            "Richards__Richards": 10358,
694*760c253cSXin Li            "RegExp__RegExp": 1765,
695*760c253cSXin Li            "NavierStokes__NavierStokes": 9815,
696*760c253cSXin Li            "Splay__Splay": 4425,
697*760c253cSXin Li            "RayTrace__RayTrace": 16600,
698*760c253cSXin Li        }
699*760c253cSXin Li        units_dict = {
700*760c253cSXin Li            "Box2D__Box2D": "score",
701*760c253cSXin Li            "Mandreel__Mandreel": "score",
702*760c253cSXin Li            "Gameboy__Gameboy": "score",
703*760c253cSXin Li            "Crypto__Crypto": "score",
704*760c253cSXin Li            "PdfJS__PdfJS": "score",
705*760c253cSXin Li            "Total__Score": "score",
706*760c253cSXin Li            "EarleyBoyer__EarleyBoyer": "score",
707*760c253cSXin Li            "MandreelLatency__MandreelLatency": "score",
708*760c253cSXin Li            "CodeLoad__CodeLoad": "score",
709*760c253cSXin Li            "DeltaBlue__DeltaBlue": "score",
710*760c253cSXin Li            "Typescript__Typescript": "score",
711*760c253cSXin Li            "SplayLatency__SplayLatency": "score",
712*760c253cSXin Li            "zlib__zlib": "score",
713*760c253cSXin Li            "Richards__Richards": "score",
714*760c253cSXin Li            "RegExp__RegExp": "score",
715*760c253cSXin Li            "NavierStokes__NavierStokes": "score",
716*760c253cSXin Li            "Splay__Splay": "score",
717*760c253cSXin Li            "RayTrace__RayTrace": "score",
718*760c253cSXin Li        }
719*760c253cSXin Li
720*760c253cSXin Li        results_dict = self.result.AppendTelemetryUnits(kv_dict, units_dict)
721*760c253cSXin Li        self.assertEqual(
722*760c253cSXin Li            results_dict,
723*760c253cSXin Li            {
724*760c253cSXin Li                "Box2D__Box2D": [4775, "score"],
725*760c253cSXin Li                "Splay__Splay": [4425, "score"],
726*760c253cSXin Li                "Gameboy__Gameboy": [9901, "score"],
727*760c253cSXin Li                "Crypto__Crypto": [8737, "score"],
728*760c253cSXin Li                "PdfJS__PdfJS": [6455, "score"],
729*760c253cSXin Li                "Total__Score": [7918, "score"],
730*760c253cSXin Li                "EarleyBoyer__EarleyBoyer": [14340, "score"],
731*760c253cSXin Li                "MandreelLatency__MandreelLatency": [5188, "score"],
732*760c253cSXin Li                "DeltaBlue__DeltaBlue": [14401, "score"],
733*760c253cSXin Li                "SplayLatency__SplayLatency": [7653, "score"],
734*760c253cSXin Li                "Mandreel__Mandreel": [6620, "score"],
735*760c253cSXin Li                "Richards__Richards": [10358, "score"],
736*760c253cSXin Li                "zlib__zlib": [16094, "score"],
737*760c253cSXin Li                "CodeLoad__CodeLoad": [6271, "score"],
738*760c253cSXin Li                "Typescript__Typescript": [9815, "score"],
739*760c253cSXin Li                "RegExp__RegExp": [1765, "score"],
740*760c253cSXin Li                "RayTrace__RayTrace": [16600, "score"],
741*760c253cSXin Li                "NavierStokes__NavierStokes": [9815, "score"],
742*760c253cSXin Li            },
743*760c253cSXin Li        )
744*760c253cSXin Li
745*760c253cSXin Li    @mock.patch.object(misc, "GetInsideChrootPath")
746*760c253cSXin Li    @mock.patch.object(tempfile, "mkdtemp")
747*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommand")
748*760c253cSXin Li    @mock.patch.object(
749*760c253cSXin Li        command_executer.CommandExecuter, "ChrootRunCommandWOutput"
750*760c253cSXin Li    )
751*760c253cSXin Li    def test_get_keyvals(
752*760c253cSXin Li        self, mock_chrootruncmd, mock_runcmd, mock_mkdtemp, mock_getpath
753*760c253cSXin Li    ):
754*760c253cSXin Li        self.kv_dict = {}
755*760c253cSXin Li        self.callGetNewKeyvals = False
756*760c253cSXin Li
757*760c253cSXin Li        def reset():
758*760c253cSXin Li            self.kv_dict = {}
759*760c253cSXin Li            self.callGetNewKeyvals = False
760*760c253cSXin Li            mock_chrootruncmd.reset_mock()
761*760c253cSXin Li            mock_runcmd.reset_mock()
762*760c253cSXin Li            mock_mkdtemp.reset_mock()
763*760c253cSXin Li            mock_getpath.reset_mock()
764*760c253cSXin Li
765*760c253cSXin Li        def FakeGetNewKeyvals(kv_dict):
766*760c253cSXin Li            self.kv_dict = kv_dict
767*760c253cSXin Li            self.callGetNewKeyvals = True
768*760c253cSXin Li            return_kvdict = {"first_time": 680, "Total": 10}
769*760c253cSXin Li            return_udict = {"first_time": "ms", "Total": "score"}
770*760c253cSXin Li            return return_kvdict, return_udict
771*760c253cSXin Li
772*760c253cSXin Li        mock_mkdtemp.return_value = TMP_DIR1
773*760c253cSXin Li        mock_chrootruncmd.return_value = [
774*760c253cSXin Li            "",
775*760c253cSXin Li            ("%s,PASS\n%s/telemetry_Crosperf,PASS\n") % (TMP_DIR1, TMP_DIR1),
776*760c253cSXin Li            "",
777*760c253cSXin Li        ]
778*760c253cSXin Li        mock_getpath.return_value = TMP_DIR1
779*760c253cSXin Li        self.result.ce.ChrootRunCommandWOutput = mock_chrootruncmd
780*760c253cSXin Li        self.result.ce.RunCommand = mock_runcmd
781*760c253cSXin Li        self.result.GetNewKeyvals = FakeGetNewKeyvals
782*760c253cSXin Li        self.result.suite = "telemetry_Crosperf"
783*760c253cSXin Li        self.result.results_dir = "/tmp/test_that_resultsNmq"
784*760c253cSXin Li
785*760c253cSXin Li        # Test 1. no self.temp_dir.
786*760c253cSXin Li        res = self.result.GetKeyvals()
787*760c253cSXin Li        self.assertTrue(self.callGetNewKeyvals)
788*760c253cSXin Li        self.assertEqual(
789*760c253cSXin Li            self.kv_dict, {"": "PASS", "telemetry_Crosperf": "PASS"}
790*760c253cSXin Li        )
791*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 1)
792*760c253cSXin Li        self.assertEqual(
793*760c253cSXin Li            mock_runcmd.call_args_list[0][0],
794*760c253cSXin Li            ("cp -r /tmp/test_that_resultsNmq/* %s" % TMP_DIR1,),
795*760c253cSXin Li        )
796*760c253cSXin Li        self.assertEqual(mock_chrootruncmd.call_count, 1)
797*760c253cSXin Li        self.assertEqual(
798*760c253cSXin Li            mock_chrootruncmd.call_args_list[0][0],
799*760c253cSXin Li            (
800*760c253cSXin Li                self.result.chromeos_root,
801*760c253cSXin Li                ("./generate_test_report --no-color --csv %s") % TMP_DIR1,
802*760c253cSXin Li            ),
803*760c253cSXin Li        )
804*760c253cSXin Li        self.assertEqual(mock_getpath.call_count, 1)
805*760c253cSXin Li        self.assertEqual(mock_mkdtemp.call_count, 1)
806*760c253cSXin Li        self.assertEqual(
807*760c253cSXin Li            res, {"Total": [10, "score"], "first_time": [680, "ms"]}
808*760c253cSXin Li        )
809*760c253cSXin Li
810*760c253cSXin Li        # Test 2. self.temp_dir
811*760c253cSXin Li        reset()
812*760c253cSXin Li        mock_chrootruncmd.return_value = [
813*760c253cSXin Li            "",
814*760c253cSXin Li            (
815*760c253cSXin Li                "/tmp/tmpJCajRG,PASS\n/tmp/tmpJCajRG/"
816*760c253cSXin Li                "telemetry_Crosperf,PASS\n"
817*760c253cSXin Li            ),
818*760c253cSXin Li            "",
819*760c253cSXin Li        ]
820*760c253cSXin Li        mock_getpath.return_value = "/tmp/tmpJCajRG"
821*760c253cSXin Li        self.result.temp_dir = "/tmp/tmpJCajRG"
822*760c253cSXin Li        res = self.result.GetKeyvals()
823*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 0)
824*760c253cSXin Li        self.assertEqual(mock_mkdtemp.call_count, 0)
825*760c253cSXin Li        self.assertEqual(mock_chrootruncmd.call_count, 1)
826*760c253cSXin Li        self.assertTrue(self.callGetNewKeyvals)
827*760c253cSXin Li        self.assertEqual(
828*760c253cSXin Li            self.kv_dict, {"": "PASS", "telemetry_Crosperf": "PASS"}
829*760c253cSXin Li        )
830*760c253cSXin Li        self.assertEqual(
831*760c253cSXin Li            res, {"Total": [10, "score"], "first_time": [680, "ms"]}
832*760c253cSXin Li        )
833*760c253cSXin Li
834*760c253cSXin Li        # Test 3. suite != telemetry_Crosperf.  Normally this would be for
835*760c253cSXin Li        # running non-Telemetry autotests, such as BootPerfServer.  In this test
836*760c253cSXin Li        # case, the keyvals we have set up were returned from a Telemetry test
837*760c253cSXin Li        # run; so this pass is basically testing that we don't append the units
838*760c253cSXin Li        # to the test results (which we do for Telemetry autotest runs).
839*760c253cSXin Li        reset()
840*760c253cSXin Li        self.result.suite = ""
841*760c253cSXin Li        res = self.result.GetKeyvals()
842*760c253cSXin Li        self.assertEqual(res, {"Total": 10, "first_time": 680})
843*760c253cSXin Li
844*760c253cSXin Li    @mock.patch.object(misc, "GetInsideChrootPath")
845*760c253cSXin Li    @mock.patch.object(
846*760c253cSXin Li        command_executer.CommandExecuter, "ChrootRunCommandWOutput"
847*760c253cSXin Li    )
848*760c253cSXin Li    @mock.patch.object(os.path, "exists")
849*760c253cSXin Li    def test_get_samples(
850*760c253cSXin Li        self, mock_exists, mock_get_total_samples, mock_getpath
851*760c253cSXin Li    ):
852*760c253cSXin Li        self.result.perf_data_files = ["/tmp/results/perf.data"]
853*760c253cSXin Li        self.result.board = "samus"
854*760c253cSXin Li        self.result.cwp_dso = "kallsyms"
855*760c253cSXin Li        mock_getpath.return_value = "/usr/chromeos/chroot/tmp/results/perf.data"
856*760c253cSXin Li        mock_get_total_samples.return_value = [
857*760c253cSXin Li            "",
858*760c253cSXin Li            (
859*760c253cSXin Li                "45.42%        53721   chrome \n"
860*760c253cSXin Li                "10.01%        12345   [kernel.kallsyms] \n"
861*760c253cSXin Li                "1.42%         1234    ssh "
862*760c253cSXin Li            ),
863*760c253cSXin Li            "",
864*760c253cSXin Li        ]
865*760c253cSXin Li        mock_exists.return_value = True
866*760c253cSXin Li
867*760c253cSXin Li        # mock_open does not seem to support iteration.
868*760c253cSXin Li        # pylint: disable=line-too-long
869*760c253cSXin Li        content = """1.63%            66  dav1d-tile       chrome                [.] decode_coefs
870*760c253cSXin Li    1.48%            60  swapper          [kernel.kallsyms]     [k] intel_idle
871*760c253cSXin Li    1.16%            47  dav1d-tile       chrome                [.] decode_sb"""
872*760c253cSXin Li
873*760c253cSXin Li        with mock.patch("builtins.open", return_value=io.StringIO(content)):
874*760c253cSXin Li            samples = self.result.GetSamples()
875*760c253cSXin Li        self.assertEqual(samples, [12345 - 60, "samples"])
876*760c253cSXin Li
877*760c253cSXin Li    def test_get_results_dir(self):
878*760c253cSXin Li        self.result.out = ""
879*760c253cSXin Li        self.assertRaises(Exception, self.result.GetResultsDir)
880*760c253cSXin Li
881*760c253cSXin Li        self.result.out = OUTPUT
882*760c253cSXin Li        resdir = self.result.GetResultsDir()
883*760c253cSXin Li        self.assertEqual(resdir, "/tmp/test_that.PO1234567/platform_LibCBench")
884*760c253cSXin Li
885*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommandGeneric")
886*760c253cSXin Li    def test_find_files_in_results_dir(self, mock_runcmd):
887*760c253cSXin Li        self.result.results_dir = None
888*760c253cSXin Li        res = self.result.FindFilesInResultsDir("-name perf.data")
889*760c253cSXin Li        self.assertEqual(res, "")
890*760c253cSXin Li
891*760c253cSXin Li        self.result.ce.RunCommand = mock_runcmd
892*760c253cSXin Li        self.result.results_dir = "/tmp/test_results"
893*760c253cSXin Li        mock_runcmd.return_value = [0, "/tmp/test_results/perf.data", ""]
894*760c253cSXin Li        res = self.result.FindFilesInResultsDir("-name perf.data")
895*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 1)
896*760c253cSXin Li        self.assertEqual(
897*760c253cSXin Li            mock_runcmd.call_args_list[0][0],
898*760c253cSXin Li            ("find /tmp/test_results -name perf.data",),
899*760c253cSXin Li        )
900*760c253cSXin Li        self.assertEqual(res, "/tmp/test_results/perf.data")
901*760c253cSXin Li
902*760c253cSXin Li        mock_runcmd.reset_mock()
903*760c253cSXin Li        mock_runcmd.return_value = [1, "", ""]
904*760c253cSXin Li        self.assertRaises(
905*760c253cSXin Li            Exception, self.result.FindFilesInResultsDir, "-name perf.data"
906*760c253cSXin Li        )
907*760c253cSXin Li
908*760c253cSXin Li    @mock.patch.object(Result, "FindFilesInResultsDir")
909*760c253cSXin Li    def test_get_perf_data_files(self, mock_findfiles):
910*760c253cSXin Li        self.args = None
911*760c253cSXin Li
912*760c253cSXin Li        mock_findfiles.return_value = "line1\nline1\n"
913*760c253cSXin Li        self.result.FindFilesInResultsDir = mock_findfiles
914*760c253cSXin Li        res = self.result.GetPerfDataFiles()
915*760c253cSXin Li        self.assertEqual(res, ["line1", "line1"])
916*760c253cSXin Li        self.assertEqual(
917*760c253cSXin Li            mock_findfiles.call_args_list[0][0], ("-name perf.data",)
918*760c253cSXin Li        )
919*760c253cSXin Li
920*760c253cSXin Li    def test_get_perf_report_files(self):
921*760c253cSXin Li        self.args = None
922*760c253cSXin Li
923*760c253cSXin Li        def FakeFindFiles(find_args):
924*760c253cSXin Li            self.args = find_args
925*760c253cSXin Li            return "line1\nline1\n"
926*760c253cSXin Li
927*760c253cSXin Li        self.result.FindFilesInResultsDir = FakeFindFiles
928*760c253cSXin Li        res = self.result.GetPerfReportFiles()
929*760c253cSXin Li        self.assertEqual(res, ["line1", "line1"])
930*760c253cSXin Li        self.assertEqual(self.args, "-name perf.data.report")
931*760c253cSXin Li
932*760c253cSXin Li    def test_get_data_measurement_files(self):
933*760c253cSXin Li        self.args = None
934*760c253cSXin Li
935*760c253cSXin Li        def FakeFindFiles(find_args):
936*760c253cSXin Li            self.args = find_args
937*760c253cSXin Li            return "line1\nline1\n"
938*760c253cSXin Li
939*760c253cSXin Li        self.result.FindFilesInResultsDir = FakeFindFiles
940*760c253cSXin Li        res = self.result.GetDataMeasurementsFiles()
941*760c253cSXin Li        self.assertEqual(res, ["line1", "line1"])
942*760c253cSXin Li        self.assertEqual(self.args, "-name perf_measurements")
943*760c253cSXin Li
944*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommandWOutput")
945*760c253cSXin Li    def test_get_turbostat_file_finds_single_log(self, mock_runcmd):
946*760c253cSXin Li        """Expected behavior when a single log file found."""
947*760c253cSXin Li        self.result.results_dir = "/tmp/test_results"
948*760c253cSXin Li        self.result.ce.RunCommandWOutput = mock_runcmd
949*760c253cSXin Li        mock_runcmd.return_value = (0, "some/long/path/turbostat.log", "")
950*760c253cSXin Li        found_single_log = self.result.GetTurbostatFile()
951*760c253cSXin Li        self.assertEqual(found_single_log, "some/long/path/turbostat.log")
952*760c253cSXin Li
953*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommandWOutput")
954*760c253cSXin Li    def test_get_turbostat_file_finds_multiple_logs(self, mock_runcmd):
955*760c253cSXin Li        """Error case when multiple files found."""
956*760c253cSXin Li        self.result.results_dir = "/tmp/test_results"
957*760c253cSXin Li        self.result.ce.RunCommandWOutput = mock_runcmd
958*760c253cSXin Li        mock_runcmd.return_value = (
959*760c253cSXin Li            0,
960*760c253cSXin Li            "some/long/path/turbostat.log\nturbostat.log",
961*760c253cSXin Li            "",
962*760c253cSXin Li        )
963*760c253cSXin Li        found_first_logs = self.result.GetTurbostatFile()
964*760c253cSXin Li        self.assertEqual(found_first_logs, "some/long/path/turbostat.log")
965*760c253cSXin Li
966*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommandWOutput")
967*760c253cSXin Li    def test_get_turbostat_file_finds_no_logs(self, mock_runcmd):
968*760c253cSXin Li        """Error case when no log file found."""
969*760c253cSXin Li        self.result.results_dir = "/tmp/test_results"
970*760c253cSXin Li        self.result.ce.RunCommandWOutput = mock_runcmd
971*760c253cSXin Li        mock_runcmd.return_value = (0, "", "")
972*760c253cSXin Li        found_no_logs = self.result.GetTurbostatFile()
973*760c253cSXin Li        self.assertEqual(found_no_logs, "")
974*760c253cSXin Li
975*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommandWOutput")
976*760c253cSXin Li    def test_get_turbostat_file_with_failing_find(self, mock_runcmd):
977*760c253cSXin Li        """Error case when file search returns an error."""
978*760c253cSXin Li        self.result.results_dir = "/tmp/test_results"
979*760c253cSXin Li        mock_runcmd.return_value = (-1, "", "error")
980*760c253cSXin Li        with self.assertRaises(RuntimeError):
981*760c253cSXin Li            self.result.GetTurbostatFile()
982*760c253cSXin Li
983*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommandWOutput")
984*760c253cSXin Li    def test_get_top_file_finds_single_log(self, mock_runcmd):
985*760c253cSXin Li        """Expected behavior when a single top log file found."""
986*760c253cSXin Li        self.result.results_dir = "/tmp/test_results"
987*760c253cSXin Li        self.result.ce.RunCommandWOutput = mock_runcmd
988*760c253cSXin Li        mock_runcmd.return_value = (0, "some/long/path/top.log", "")
989*760c253cSXin Li        found_single_log = self.result.GetTopFile()
990*760c253cSXin Li        self.assertEqual(found_single_log, "some/long/path/top.log")
991*760c253cSXin Li
992*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommandWOutput")
993*760c253cSXin Li    def test_get_top_file_finds_multiple_logs(self, mock_runcmd):
994*760c253cSXin Li        """The case when multiple top files found."""
995*760c253cSXin Li        self.result.results_dir = "/tmp/test_results"
996*760c253cSXin Li        self.result.ce.RunCommandWOutput = mock_runcmd
997*760c253cSXin Li        mock_runcmd.return_value = (0, "some/long/path/top.log\ntop.log", "")
998*760c253cSXin Li        found_first_logs = self.result.GetTopFile()
999*760c253cSXin Li        self.assertEqual(found_first_logs, "some/long/path/top.log")
1000*760c253cSXin Li
1001*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommandWOutput")
1002*760c253cSXin Li    def test_get_top_file_finds_no_logs(self, mock_runcmd):
1003*760c253cSXin Li        """Error case when no log file found."""
1004*760c253cSXin Li        self.result.results_dir = "/tmp/test_results"
1005*760c253cSXin Li        self.result.ce.RunCommandWOutput = mock_runcmd
1006*760c253cSXin Li        mock_runcmd.return_value = (0, "", "")
1007*760c253cSXin Li        found_no_logs = self.result.GetTopFile()
1008*760c253cSXin Li        self.assertEqual(found_no_logs, "")
1009*760c253cSXin Li
1010*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommandWOutput")
1011*760c253cSXin Li    def test_get_cpuinfo_file_finds_single_log(self, mock_runcmd):
1012*760c253cSXin Li        """Expected behavior when a single cpuinfo file found."""
1013*760c253cSXin Li        self.result.results_dir = "/tmp/test_results"
1014*760c253cSXin Li        self.result.ce.RunCommandWOutput = mock_runcmd
1015*760c253cSXin Li        mock_runcmd.return_value = (0, "some/long/path/cpuinfo.log", "")
1016*760c253cSXin Li        found_single_log = self.result.GetCpuinfoFile()
1017*760c253cSXin Li        self.assertEqual(found_single_log, "some/long/path/cpuinfo.log")
1018*760c253cSXin Li
1019*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommandWOutput")
1020*760c253cSXin Li    def test_get_cpustats_file_finds_single_log(self, mock_runcmd):
1021*760c253cSXin Li        """Expected behavior when a single log file found."""
1022*760c253cSXin Li        self.result.results_dir = "/tmp/test_results"
1023*760c253cSXin Li        self.result.ce.RunCommandWOutput = mock_runcmd
1024*760c253cSXin Li        mock_runcmd.return_value = (0, "some/long/path/cpustats.log", "")
1025*760c253cSXin Li        found_single_log = self.result.GetCpustatsFile()
1026*760c253cSXin Li        self.assertEqual(found_single_log, "some/long/path/cpustats.log")
1027*760c253cSXin Li
1028*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommandWOutput")
1029*760c253cSXin Li    def test_get_cpustats_file_finds_multiple_logs(self, mock_runcmd):
1030*760c253cSXin Li        """The case when multiple files found."""
1031*760c253cSXin Li        self.result.results_dir = "/tmp/test_results"
1032*760c253cSXin Li        self.result.ce.RunCommandWOutput = mock_runcmd
1033*760c253cSXin Li        mock_runcmd.return_value = (
1034*760c253cSXin Li            0,
1035*760c253cSXin Li            "some/long/path/cpustats.log\ncpustats.log",
1036*760c253cSXin Li            "",
1037*760c253cSXin Li        )
1038*760c253cSXin Li        found_first_logs = self.result.GetCpustatsFile()
1039*760c253cSXin Li        self.assertEqual(found_first_logs, "some/long/path/cpustats.log")
1040*760c253cSXin Li
1041*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommandWOutput")
1042*760c253cSXin Li    def test_get_cpustats_file_finds_no_logs(self, mock_runcmd):
1043*760c253cSXin Li        """Error case when no log file found."""
1044*760c253cSXin Li        self.result.results_dir = "/tmp/test_results"
1045*760c253cSXin Li        self.result.ce.RunCommandWOutput = mock_runcmd
1046*760c253cSXin Li        mock_runcmd.return_value = (0, "", "")
1047*760c253cSXin Li        found_no_logs = self.result.GetCpustatsFile()
1048*760c253cSXin Li        self.assertEqual(found_no_logs, "")
1049*760c253cSXin Li
1050*760c253cSXin Li    def test_verify_perf_data_pid_ok(self):
1051*760c253cSXin Li        """Verify perf PID which is present in TOP_DATA."""
1052*760c253cSXin Li        self.result.top_cmds = TOP_DATA
1053*760c253cSXin Li        # pid is present in TOP_DATA.
1054*760c253cSXin Li        with mock.patch.object(
1055*760c253cSXin Li            Result, "ReadPidFromPerfData", return_value=["5713"]
1056*760c253cSXin Li        ):
1057*760c253cSXin Li            self.result.VerifyPerfDataPID()
1058*760c253cSXin Li
1059*760c253cSXin Li    def test_verify_perf_data_pid_fail(self):
1060*760c253cSXin Li        """Test perf PID missing in top raises the error."""
1061*760c253cSXin Li        self.result.top_cmds = TOP_DATA
1062*760c253cSXin Li        # pid is not in the list of top processes.
1063*760c253cSXin Li        with mock.patch.object(
1064*760c253cSXin Li            Result, "ReadPidFromPerfData", return_value=["9999"]
1065*760c253cSXin Li        ):
1066*760c253cSXin Li            with self.assertRaises(PidVerificationError):
1067*760c253cSXin Li                self.result.VerifyPerfDataPID()
1068*760c253cSXin Li
1069*760c253cSXin Li    @mock.patch.object(
1070*760c253cSXin Li        command_executer.CommandExecuter, "ChrootRunCommandWOutput"
1071*760c253cSXin Li    )
1072*760c253cSXin Li    def test_read_pid_from_perf_data_ok(self, mock_runcmd):
1073*760c253cSXin Li        """Test perf header parser, normal flow."""
1074*760c253cSXin Li        self.result.ce.ChrootRunCommandWOutput = mock_runcmd
1075*760c253cSXin Li        self.result.perf_data_files = [
1076*760c253cSXin Li            "/tmp/chromeos/chroot/tmp/results/perf.data"
1077*760c253cSXin Li        ]
1078*760c253cSXin Li        exp_pid = "12345"
1079*760c253cSXin Li        mock_runcmd.return_value = (0, PERF_DATA_HEADER.format(pid=exp_pid), "")
1080*760c253cSXin Li        pids = self.result.ReadPidFromPerfData()
1081*760c253cSXin Li        self.assertEqual(pids, [exp_pid])
1082*760c253cSXin Li
1083*760c253cSXin Li    @mock.patch.object(
1084*760c253cSXin Li        command_executer.CommandExecuter, "ChrootRunCommandWOutput"
1085*760c253cSXin Li    )
1086*760c253cSXin Li    def test_read_pid_from_perf_data_mult_profiles(self, mock_runcmd):
1087*760c253cSXin Li        """Test multiple perf.data files with PID."""
1088*760c253cSXin Li        self.result.ce.ChrootRunCommandWOutput = mock_runcmd
1089*760c253cSXin Li        # self.result.chromeos_root = '/tmp/chromeos'
1090*760c253cSXin Li        self.result.perf_data_files = [
1091*760c253cSXin Li            "/tmp/chromeos/chroot/tmp/results/perf.data.0",
1092*760c253cSXin Li            "/tmp/chromeos/chroot/tmp/results/perf.data.1",
1093*760c253cSXin Li        ]
1094*760c253cSXin Li        # There is '-p <pid>' in command line but it's still system-wide: '-a'.
1095*760c253cSXin Li        cmd_line = "# cmdline : /usr/bin/perf record -e instructions -p {pid}"
1096*760c253cSXin Li        exp_perf_pids = ["1111", "2222"]
1097*760c253cSXin Li        mock_runcmd.side_effect = [
1098*760c253cSXin Li            (0, cmd_line.format(pid=exp_perf_pids[0]), ""),
1099*760c253cSXin Li            (0, cmd_line.format(pid=exp_perf_pids[1]), ""),
1100*760c253cSXin Li        ]
1101*760c253cSXin Li        pids = self.result.ReadPidFromPerfData()
1102*760c253cSXin Li        self.assertEqual(pids, exp_perf_pids)
1103*760c253cSXin Li
1104*760c253cSXin Li    @mock.patch.object(
1105*760c253cSXin Li        command_executer.CommandExecuter, "ChrootRunCommandWOutput"
1106*760c253cSXin Li    )
1107*760c253cSXin Li    def test_read_pid_from_perf_data_no_pid(self, mock_runcmd):
1108*760c253cSXin Li        """Test perf.data without PID."""
1109*760c253cSXin Li        self.result.ce.ChrootRunCommandWOutput = mock_runcmd
1110*760c253cSXin Li        self.result.perf_data_files = [
1111*760c253cSXin Li            "/tmp/chromeos/chroot/tmp/results/perf.data"
1112*760c253cSXin Li        ]
1113*760c253cSXin Li        cmd_line = "# cmdline : /usr/bin/perf record -e instructions"
1114*760c253cSXin Li        mock_runcmd.return_value = (0, cmd_line, "")
1115*760c253cSXin Li        pids = self.result.ReadPidFromPerfData()
1116*760c253cSXin Li        # pids is empty.
1117*760c253cSXin Li        self.assertEqual(pids, [])
1118*760c253cSXin Li
1119*760c253cSXin Li    @mock.patch.object(
1120*760c253cSXin Li        command_executer.CommandExecuter, "ChrootRunCommandWOutput"
1121*760c253cSXin Li    )
1122*760c253cSXin Li    def test_read_pid_from_perf_data_system_wide(self, mock_runcmd):
1123*760c253cSXin Li        """Test reading from system-wide profile with PID."""
1124*760c253cSXin Li        self.result.ce.ChrootRunCommandWOutput = mock_runcmd
1125*760c253cSXin Li        self.result.perf_data_files = [
1126*760c253cSXin Li            "/tmp/chromeos/chroot/tmp/results/perf.data"
1127*760c253cSXin Li        ]
1128*760c253cSXin Li        # There is '-p <pid>' in command line but it's still system-wide: '-a'.
1129*760c253cSXin Li        cmd_line = "# cmdline : /usr/bin/perf record -e instructions -a -p 1234"
1130*760c253cSXin Li        mock_runcmd.return_value = (0, cmd_line, "")
1131*760c253cSXin Li        pids = self.result.ReadPidFromPerfData()
1132*760c253cSXin Li        # pids should be empty since it's not a per-process profiling.
1133*760c253cSXin Li        self.assertEqual(pids, [])
1134*760c253cSXin Li
1135*760c253cSXin Li    @mock.patch.object(
1136*760c253cSXin Li        command_executer.CommandExecuter, "ChrootRunCommandWOutput"
1137*760c253cSXin Li    )
1138*760c253cSXin Li    def test_read_pid_from_perf_data_read_fail(self, mock_runcmd):
1139*760c253cSXin Li        """Failure to read perf.data raises the error."""
1140*760c253cSXin Li        self.result.ce.ChrootRunCommandWOutput = mock_runcmd
1141*760c253cSXin Li        self.result.perf_data_files = [
1142*760c253cSXin Li            "/tmp/chromeos/chroot/tmp/results/perf.data"
1143*760c253cSXin Li        ]
1144*760c253cSXin Li        # Error status of the profile read.
1145*760c253cSXin Li        mock_runcmd.return_value = (1, "", "")
1146*760c253cSXin Li        with self.assertRaises(PerfDataReadError):
1147*760c253cSXin Li            self.result.ReadPidFromPerfData()
1148*760c253cSXin Li
1149*760c253cSXin Li    @mock.patch.object(
1150*760c253cSXin Li        command_executer.CommandExecuter, "ChrootRunCommandWOutput"
1151*760c253cSXin Li    )
1152*760c253cSXin Li    def test_read_pid_from_perf_data_fail(self, mock_runcmd):
1153*760c253cSXin Li        """Failure to find cmdline in perf.data header raises the error."""
1154*760c253cSXin Li        self.result.ce.ChrootRunCommandWOutput = mock_runcmd
1155*760c253cSXin Li        self.result.perf_data_files = [
1156*760c253cSXin Li            "/tmp/chromeos/chroot/tmp/results/perf.data"
1157*760c253cSXin Li        ]
1158*760c253cSXin Li        # Empty output.
1159*760c253cSXin Li        mock_runcmd.return_value = (0, "", "")
1160*760c253cSXin Li        with self.assertRaises(PerfDataReadError):
1161*760c253cSXin Li            self.result.ReadPidFromPerfData()
1162*760c253cSXin Li
1163*760c253cSXin Li    def test_process_turbostat_results_with_valid_data(self):
1164*760c253cSXin Li        """Normal case when log exists and contains valid data."""
1165*760c253cSXin Li        self.result.turbostat_log_file = "/tmp/somelogfile.log"
1166*760c253cSXin Li        with mock.patch(
1167*760c253cSXin Li            "builtins.open",
1168*760c253cSXin Li            mock.mock_open(read_data=TURBOSTAT_LOG_OUTPUT),
1169*760c253cSXin Li        ) as mo:
1170*760c253cSXin Li            cpustats = self.result.ProcessTurbostatResults()
1171*760c253cSXin Li            # Check that the log got opened and data were read/parsed.
1172*760c253cSXin Li            calls = [mock.call("/tmp/somelogfile.log", encoding="utf-8")]
1173*760c253cSXin Li            mo.assert_has_calls(calls)
1174*760c253cSXin Li            self.assertEqual(cpustats, TURBOSTAT_DATA)
1175*760c253cSXin Li
1176*760c253cSXin Li    def test_process_turbostat_results_from_empty_file(self):
1177*760c253cSXin Li        """Error case when log exists but file is empty."""
1178*760c253cSXin Li        self.result.turbostat_log_file = "/tmp/emptylogfile.log"
1179*760c253cSXin Li        with mock.patch("builtins.open", mock.mock_open(read_data="")) as mo:
1180*760c253cSXin Li            cpustats = self.result.ProcessTurbostatResults()
1181*760c253cSXin Li            # Check that the log got opened and parsed successfully and empty
1182*760c253cSXin Li            # data returned.
1183*760c253cSXin Li            calls = [mock.call("/tmp/emptylogfile.log", encoding="utf-8")]
1184*760c253cSXin Li            mo.assert_has_calls(calls)
1185*760c253cSXin Li            self.assertEqual(cpustats, {})
1186*760c253cSXin Li
1187*760c253cSXin Li    def test_process_turbostat_results_when_file_doesnt_exist(self):
1188*760c253cSXin Li        """Error case when file does not exist."""
1189*760c253cSXin Li        nonexistinglog = "/tmp/1"
1190*760c253cSXin Li        while os.path.exists(nonexistinglog):
1191*760c253cSXin Li            # Extend file path if it happens to exist.
1192*760c253cSXin Li            nonexistinglog = os.path.join(nonexistinglog, "1")
1193*760c253cSXin Li        self.result.turbostat_log_file = nonexistinglog
1194*760c253cSXin Li        # Allow the tested function to call a 'real' open and hopefully crash.
1195*760c253cSXin Li        with self.assertRaises(IOError):
1196*760c253cSXin Li            self.result.ProcessTurbostatResults()
1197*760c253cSXin Li
1198*760c253cSXin Li    def test_process_cpustats_results_with_uniq_data(self):
1199*760c253cSXin Li        """Process cpustats log which has freq unique to each core.
1200*760c253cSXin Li
1201*760c253cSXin Li        Testing normal case when frequency data vary between
1202*760c253cSXin Li        different cores.
1203*760c253cSXin Li        Expecting that data for all cores will be present in
1204*760c253cSXin Li        returned cpustats.
1205*760c253cSXin Li        """
1206*760c253cSXin Li        self.result.cpustats_log_file = "/tmp/somelogfile.log"
1207*760c253cSXin Li        with mock.patch(
1208*760c253cSXin Li            "builtins.open",
1209*760c253cSXin Li            mock.mock_open(read_data=CPUSTATS_UNIQ_OUTPUT),
1210*760c253cSXin Li        ) as mo:
1211*760c253cSXin Li            cpustats = self.result.ProcessCpustatsResults()
1212*760c253cSXin Li            # Check that the log got opened and data were read/parsed.
1213*760c253cSXin Li            calls = [mock.call("/tmp/somelogfile.log", encoding="utf-8")]
1214*760c253cSXin Li            mo.assert_has_calls(calls)
1215*760c253cSXin Li            self.assertEqual(cpustats, CPUSTATS_UNIQ_DATA)
1216*760c253cSXin Li
1217*760c253cSXin Li    def test_process_cpustats_results_with_dupl_data(self):
1218*760c253cSXin Li        """Process cpustats log where cores have duplicate freq.
1219*760c253cSXin Li
1220*760c253cSXin Li        Testing normal case when frequency data on some cores
1221*760c253cSXin Li        are duplicated.
1222*760c253cSXin Li        Expecting that duplicated data is discarded in
1223*760c253cSXin Li        returned cpustats.
1224*760c253cSXin Li        """
1225*760c253cSXin Li        self.result.cpustats_log_file = "/tmp/somelogfile.log"
1226*760c253cSXin Li        with mock.patch(
1227*760c253cSXin Li            "builtins.open",
1228*760c253cSXin Li            mock.mock_open(read_data=CPUSTATS_DUPL_OUTPUT),
1229*760c253cSXin Li        ) as mo:
1230*760c253cSXin Li            cpustats = self.result.ProcessCpustatsResults()
1231*760c253cSXin Li            # Check that the log got opened and data were read/parsed.
1232*760c253cSXin Li            calls = [mock.call("/tmp/somelogfile.log", encoding="utf-8")]
1233*760c253cSXin Li            mo.assert_has_calls(calls)
1234*760c253cSXin Li            self.assertEqual(cpustats, CPUSTATS_DUPL_DATA)
1235*760c253cSXin Li
1236*760c253cSXin Li    def test_process_cpustats_results_from_empty_file(self):
1237*760c253cSXin Li        """Error case when log exists but file is empty."""
1238*760c253cSXin Li        self.result.cpustats_log_file = "/tmp/emptylogfile.log"
1239*760c253cSXin Li        with mock.patch("builtins.open", mock.mock_open(read_data="")) as mo:
1240*760c253cSXin Li            cpustats = self.result.ProcessCpustatsResults()
1241*760c253cSXin Li            # Check that the log got opened and parsed successfully and empty
1242*760c253cSXin Li            # data returned.
1243*760c253cSXin Li            calls = [mock.call("/tmp/emptylogfile.log", encoding="utf-8")]
1244*760c253cSXin Li            mo.assert_has_calls(calls)
1245*760c253cSXin Li            self.assertEqual(cpustats, {})
1246*760c253cSXin Li
1247*760c253cSXin Li    def test_process_top_results_with_valid_data(self):
1248*760c253cSXin Li        """Process top log with valid data."""
1249*760c253cSXin Li
1250*760c253cSXin Li        self.result.top_log_file = "/tmp/fakelogfile.log"
1251*760c253cSXin Li        with mock.patch(
1252*760c253cSXin Li            "builtins.open", mock.mock_open(read_data=TOP_LOG)
1253*760c253cSXin Li        ) as mo:
1254*760c253cSXin Li            topproc = self.result.ProcessTopResults()
1255*760c253cSXin Li            # Check that the log got opened and data were read/parsed.
1256*760c253cSXin Li            calls = [mock.call("/tmp/fakelogfile.log", encoding="utf-8")]
1257*760c253cSXin Li            mo.assert_has_calls(calls)
1258*760c253cSXin Li            self.assertEqual(topproc, TOP_DATA)
1259*760c253cSXin Li
1260*760c253cSXin Li    def test_process_top_results_from_empty_file(self):
1261*760c253cSXin Li        """Error case when log exists but file is empty."""
1262*760c253cSXin Li        self.result.top_log_file = "/tmp/emptylogfile.log"
1263*760c253cSXin Li        with mock.patch("builtins.open", mock.mock_open(read_data="")) as mo:
1264*760c253cSXin Li            topcalls = self.result.ProcessTopResults()
1265*760c253cSXin Li            # Check that the log got opened and parsed successfully and empty
1266*760c253cSXin Li            # data returned.
1267*760c253cSXin Li            calls = [mock.call("/tmp/emptylogfile.log", encoding="utf-8")]
1268*760c253cSXin Li            mo.assert_has_calls(calls)
1269*760c253cSXin Li            self.assertEqual(topcalls, [])
1270*760c253cSXin Li
1271*760c253cSXin Li    def test_format_string_top_cmds(self):
1272*760c253cSXin Li        """Test formatted string with top commands."""
1273*760c253cSXin Li        self.result.top_cmds = [
1274*760c253cSXin Li            {
1275*760c253cSXin Li                "cmd": "chrome-111",
1276*760c253cSXin Li                "cpu_use_avg": 119.753453465,
1277*760c253cSXin Li                "count": 44444,
1278*760c253cSXin Li                "top5_cpu_use": [222.8, 217.9, 217.8, 191.0, 189.9],
1279*760c253cSXin Li            },
1280*760c253cSXin Li            {
1281*760c253cSXin Li                "cmd": "chrome-222",
1282*760c253cSXin Li                "cpu_use_avg": 100,
1283*760c253cSXin Li                "count": 33333,
1284*760c253cSXin Li                "top5_cpu_use": [200.0, 195.0, 190.0, 185.0, 180.0],
1285*760c253cSXin Li            },
1286*760c253cSXin Li            {
1287*760c253cSXin Li                "cmd": "irq/230-cros-ec",
1288*760c253cSXin Li                "cpu_use_avg": 10.000000000000001,
1289*760c253cSXin Li                "count": 1000,
1290*760c253cSXin Li                "top5_cpu_use": [11.5, 11.4, 11.3, 11.2, 11.1],
1291*760c253cSXin Li            },
1292*760c253cSXin Li            {
1293*760c253cSXin Li                "cmd": "powerd",
1294*760c253cSXin Li                "cpu_use_avg": 2.0,
1295*760c253cSXin Li                "count": 2,
1296*760c253cSXin Li                "top5_cpu_use": [3.0, 1.0],
1297*760c253cSXin Li            },
1298*760c253cSXin Li            {
1299*760c253cSXin Li                "cmd": "cmd3",
1300*760c253cSXin Li                "cpu_use_avg": 1.0,
1301*760c253cSXin Li                "count": 1,
1302*760c253cSXin Li                "top5_cpu_use": [1.0],
1303*760c253cSXin Li            },
1304*760c253cSXin Li            {
1305*760c253cSXin Li                "cmd": "cmd4",
1306*760c253cSXin Li                "cpu_use_avg": 1.0,
1307*760c253cSXin Li                "count": 1,
1308*760c253cSXin Li                "top5_cpu_use": [1.0],
1309*760c253cSXin Li            },
1310*760c253cSXin Li            {
1311*760c253cSXin Li                "cmd": "cmd5",
1312*760c253cSXin Li                "cpu_use_avg": 1.0,
1313*760c253cSXin Li                "count": 1,
1314*760c253cSXin Li                "top5_cpu_use": [1.0],
1315*760c253cSXin Li            },
1316*760c253cSXin Li            {
1317*760c253cSXin Li                "cmd": "cmd6_not_for_print",
1318*760c253cSXin Li                "cpu_avg": 1.0,
1319*760c253cSXin Li                "count": 1,
1320*760c253cSXin Li                "top5": [1.0],
1321*760c253cSXin Li            },
1322*760c253cSXin Li        ]
1323*760c253cSXin Li        form_str = self.result.FormatStringTopCommands()
1324*760c253cSXin Li        self.assertEqual(
1325*760c253cSXin Li            form_str,
1326*760c253cSXin Li            "\n".join(
1327*760c253cSXin Li                [
1328*760c253cSXin Li                    "Top commands with highest CPU usage:",
1329*760c253cSXin Li                    "             COMMAND  AVG CPU%  COUNT   HIGHEST 5",
1330*760c253cSXin Li                    "-" * 50,
1331*760c253cSXin Li                    "          chrome-111    119.75  44444   "
1332*760c253cSXin Li                    "[222.8, 217.9, 217.8, 191.0, 189.9]",
1333*760c253cSXin Li                    "          chrome-222    100.00  33333   "
1334*760c253cSXin Li                    "[200.0, 195.0, 190.0, 185.0, 180.0]",
1335*760c253cSXin Li                    "     irq/230-cros-ec     10.00   1000   "
1336*760c253cSXin Li                    "[11.5, 11.4, 11.3, 11.2, 11.1]",
1337*760c253cSXin Li                    "              powerd      2.00      2   [3.0, 1.0]",
1338*760c253cSXin Li                    "                cmd3      1.00      1   [1.0]",
1339*760c253cSXin Li                    "                cmd4      1.00      1   [1.0]",
1340*760c253cSXin Li                    "                cmd5      1.00      1   [1.0]",
1341*760c253cSXin Li                    "-" * 50,
1342*760c253cSXin Li                ]
1343*760c253cSXin Li            ),
1344*760c253cSXin Li        )
1345*760c253cSXin Li
1346*760c253cSXin Li    def test_format_string_top_calls_no_data(self):
1347*760c253cSXin Li        """Test formatted string of top with no data."""
1348*760c253cSXin Li        self.result.top_cmds = []
1349*760c253cSXin Li        form_str = self.result.FormatStringTopCommands()
1350*760c253cSXin Li        self.assertEqual(
1351*760c253cSXin Li            form_str,
1352*760c253cSXin Li            "\n".join(
1353*760c253cSXin Li                [
1354*760c253cSXin Li                    "Top commands with highest CPU usage:",
1355*760c253cSXin Li                    "             COMMAND  AVG CPU%  COUNT   HIGHEST 5",
1356*760c253cSXin Li                    "-" * 50,
1357*760c253cSXin Li                    "[NO DATA FROM THE TOP LOG]",
1358*760c253cSXin Li                    "-" * 50,
1359*760c253cSXin Li                ]
1360*760c253cSXin Li            ),
1361*760c253cSXin Li        )
1362*760c253cSXin Li
1363*760c253cSXin Li    @mock.patch.object(os.path, "exists")
1364*760c253cSXin Li    @mock.patch.object(misc, "GetInsideChrootPath")
1365*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "ChrootRunCommand")
1366*760c253cSXin Li    def test_generate_perf_report_files(
1367*760c253cSXin Li        self, mock_chrootruncmd, mock_getpath, mock_pathexists
1368*760c253cSXin Li    ):
1369*760c253cSXin Li        mock_pathexists.side_effect = (
1370*760c253cSXin Li            lambda x: self.orig_exists(x)
1371*760c253cSXin Li            if x != "/etc/cros_chroot_version"
1372*760c253cSXin Li            else False
1373*760c253cSXin Li        )
1374*760c253cSXin Li        fake_file = "/tmp/results/perf.data.report"
1375*760c253cSXin Li        self.result.perf_data_files = ["/tmp/results/perf.data"]
1376*760c253cSXin Li        self.result.board = "lumpy"
1377*760c253cSXin Li        mock_getpath.return_value = fake_file
1378*760c253cSXin Li        self.result.ce.ChrootRunCommand = mock_chrootruncmd
1379*760c253cSXin Li        mock_chrootruncmd.return_value = 0
1380*760c253cSXin Li        # Debug path not found
1381*760c253cSXin Li        self.result.label.debug_path = ""
1382*760c253cSXin Li        tmp = self.result.GeneratePerfReportFiles()
1383*760c253cSXin Li        self.assertEqual(len(tmp), 1)
1384*760c253cSXin Li        self.assertEqual(tmp[0], RegexMatcher("/tmp/chromeos.*%s" % fake_file))
1385*760c253cSXin Li        self.assertEqual(
1386*760c253cSXin Li            mock_chrootruncmd.call_args_list[0][0],
1387*760c253cSXin Li            (
1388*760c253cSXin Li                self.result.chromeos_root,
1389*760c253cSXin Li                ("/usr/sbin/perf report -n    " "-i %s --stdio > %s")
1390*760c253cSXin Li                % (fake_file, fake_file),
1391*760c253cSXin Li            ),
1392*760c253cSXin Li        )
1393*760c253cSXin Li
1394*760c253cSXin Li    @mock.patch.object(os.path, "exists")
1395*760c253cSXin Li    @mock.patch.object(misc, "GetInsideChrootPath")
1396*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "ChrootRunCommand")
1397*760c253cSXin Li    def test_generate_perf_report_files_debug(
1398*760c253cSXin Li        self, mock_chrootruncmd, mock_getpath, mock_pathexists
1399*760c253cSXin Li    ):
1400*760c253cSXin Li        mock_pathexists.side_effect = (
1401*760c253cSXin Li            lambda x: self.orig_exists(x)
1402*760c253cSXin Li            if x != "/etc/cros_chroot_version"
1403*760c253cSXin Li            else False
1404*760c253cSXin Li        )
1405*760c253cSXin Li        fake_file = "/tmp/results/perf.data.report"
1406*760c253cSXin Li        self.result.perf_data_files = ["/tmp/results/perf.data"]
1407*760c253cSXin Li        self.result.board = "lumpy"
1408*760c253cSXin Li        mock_getpath.return_value = fake_file
1409*760c253cSXin Li        self.result.ce.ChrootRunCommand = mock_chrootruncmd
1410*760c253cSXin Li        mock_chrootruncmd.return_value = 0
1411*760c253cSXin Li        # Debug path found
1412*760c253cSXin Li        self.result.label.debug_path = "/tmp/debug"
1413*760c253cSXin Li        tmp = self.result.GeneratePerfReportFiles()
1414*760c253cSXin Li        self.assertEqual(len(tmp), 1)
1415*760c253cSXin Li        self.assertEqual(tmp[0], RegexMatcher("/tmp/chromeos.*%s" % fake_file))
1416*760c253cSXin Li        self.assertEqual(
1417*760c253cSXin Li            mock_chrootruncmd.call_args_list[0][0],
1418*760c253cSXin Li            (
1419*760c253cSXin Li                self.result.chromeos_root,
1420*760c253cSXin Li                (
1421*760c253cSXin Li                    "/usr/sbin/perf report -n --symfs /tmp/debug "
1422*760c253cSXin Li                    "--vmlinux /tmp/debug/usr/lib/debug/boot/vmlinux  "
1423*760c253cSXin Li                    "-i %s --stdio > %s"
1424*760c253cSXin Li                )
1425*760c253cSXin Li                % (fake_file, fake_file),
1426*760c253cSXin Li            ),
1427*760c253cSXin Li        )
1428*760c253cSXin Li
1429*760c253cSXin Li    @mock.patch.object(misc, "GetOutsideChrootPath")
1430*760c253cSXin Li    def test_populate_from_run(self, mock_getpath):
1431*760c253cSXin Li        def FakeGetResultsDir():
1432*760c253cSXin Li            self.callGetResultsDir = True
1433*760c253cSXin Li            return "/tmp/results_dir"
1434*760c253cSXin Li
1435*760c253cSXin Li        def FakeGetResultsFile():
1436*760c253cSXin Li            self.callGetResultsFile = True
1437*760c253cSXin Li            return []
1438*760c253cSXin Li
1439*760c253cSXin Li        def FakeGetPerfDataFiles():
1440*760c253cSXin Li            self.callGetPerfDataFiles = True
1441*760c253cSXin Li            return []
1442*760c253cSXin Li
1443*760c253cSXin Li        def FakeGetPerfReportFiles():
1444*760c253cSXin Li            self.callGetPerfReportFiles = True
1445*760c253cSXin Li            return []
1446*760c253cSXin Li
1447*760c253cSXin Li        def FakeGetTurbostatFile():
1448*760c253cSXin Li            self.callGetTurbostatFile = True
1449*760c253cSXin Li            return []
1450*760c253cSXin Li
1451*760c253cSXin Li        def FakeGetCpustatsFile():
1452*760c253cSXin Li            self.callGetCpustatsFile = True
1453*760c253cSXin Li            return []
1454*760c253cSXin Li
1455*760c253cSXin Li        def FakeGetTopFile():
1456*760c253cSXin Li            self.callGetTopFile = True
1457*760c253cSXin Li            return []
1458*760c253cSXin Li
1459*760c253cSXin Li        def FakeGetCpuinfoFile():
1460*760c253cSXin Li            self.callGetCpuinfoFile = True
1461*760c253cSXin Li            return []
1462*760c253cSXin Li
1463*760c253cSXin Li        def FakeGetWaitTimeFile():
1464*760c253cSXin Li            self.callGetWaitTimeFile = True
1465*760c253cSXin Li            return []
1466*760c253cSXin Li
1467*760c253cSXin Li        def FakeProcessResults(show_results=False):
1468*760c253cSXin Li            if show_results:
1469*760c253cSXin Li                pass
1470*760c253cSXin Li            self.callProcessResults = True
1471*760c253cSXin Li
1472*760c253cSXin Li        if mock_getpath:
1473*760c253cSXin Li            pass
1474*760c253cSXin Li        mock.get_path = "/tmp/chromeos/tmp/results_dir"
1475*760c253cSXin Li
1476*760c253cSXin Li        self.callGetResultsDir = False
1477*760c253cSXin Li        self.callGetResultsFile = False
1478*760c253cSXin Li        self.callGetPerfDataFiles = False
1479*760c253cSXin Li        self.callGetPerfReportFiles = False
1480*760c253cSXin Li        self.callGetTurbostatFile = False
1481*760c253cSXin Li        self.callGetCpustatsFile = False
1482*760c253cSXin Li        self.callGetTopFile = False
1483*760c253cSXin Li        self.callGetCpuinfoFile = False
1484*760c253cSXin Li        self.callGetWaitTimeFile = False
1485*760c253cSXin Li        self.callProcessResults = False
1486*760c253cSXin Li
1487*760c253cSXin Li        self.result.GetResultsDir = FakeGetResultsDir
1488*760c253cSXin Li        self.result.GetResultsFile = FakeGetResultsFile
1489*760c253cSXin Li        self.result.GetPerfDataFiles = FakeGetPerfDataFiles
1490*760c253cSXin Li        self.result.GeneratePerfReportFiles = FakeGetPerfReportFiles
1491*760c253cSXin Li        self.result.GetTurbostatFile = FakeGetTurbostatFile
1492*760c253cSXin Li        self.result.GetCpustatsFile = FakeGetCpustatsFile
1493*760c253cSXin Li        self.result.GetTopFile = FakeGetTopFile
1494*760c253cSXin Li        self.result.GetCpuinfoFile = FakeGetCpuinfoFile
1495*760c253cSXin Li        self.result.GetWaitTimeFile = FakeGetWaitTimeFile
1496*760c253cSXin Li        self.result.ProcessResults = FakeProcessResults
1497*760c253cSXin Li
1498*760c253cSXin Li        self.result.PopulateFromRun(
1499*760c253cSXin Li            OUTPUT, "", 0, "test", "telemetry_Crosperf", "chrome"
1500*760c253cSXin Li        )
1501*760c253cSXin Li        self.assertTrue(self.callGetResultsDir)
1502*760c253cSXin Li        self.assertTrue(self.callGetResultsFile)
1503*760c253cSXin Li        self.assertTrue(self.callGetPerfDataFiles)
1504*760c253cSXin Li        self.assertTrue(self.callGetPerfReportFiles)
1505*760c253cSXin Li        self.assertTrue(self.callGetTurbostatFile)
1506*760c253cSXin Li        self.assertTrue(self.callGetCpustatsFile)
1507*760c253cSXin Li        self.assertTrue(self.callGetTopFile)
1508*760c253cSXin Li        self.assertTrue(self.callGetCpuinfoFile)
1509*760c253cSXin Li        self.assertTrue(self.callGetWaitTimeFile)
1510*760c253cSXin Li        self.assertTrue(self.callProcessResults)
1511*760c253cSXin Li
1512*760c253cSXin Li    def FakeGetKeyvals(self, show_all=False):
1513*760c253cSXin Li        if show_all:
1514*760c253cSXin Li            return {"first_time": 680, "Total": 10}
1515*760c253cSXin Li        else:
1516*760c253cSXin Li            return {"Total": 10}
1517*760c253cSXin Li
1518*760c253cSXin Li    def test_process_results(self):
1519*760c253cSXin Li        def FakeGatherPerfResults():
1520*760c253cSXin Li            self.callGatherPerfResults = True
1521*760c253cSXin Li
1522*760c253cSXin Li        def FakeGetSamples():
1523*760c253cSXin Li            return (1, "samples")
1524*760c253cSXin Li
1525*760c253cSXin Li        # Test 1
1526*760c253cSXin Li        self.callGatherPerfResults = False
1527*760c253cSXin Li
1528*760c253cSXin Li        self.result.GetKeyvals = self.FakeGetKeyvals
1529*760c253cSXin Li        self.result.GatherPerfResults = FakeGatherPerfResults
1530*760c253cSXin Li
1531*760c253cSXin Li        self.result.retval = 0
1532*760c253cSXin Li        self.result.ProcessResults()
1533*760c253cSXin Li        self.assertTrue(self.callGatherPerfResults)
1534*760c253cSXin Li        self.assertEqual(len(self.result.keyvals), 2)
1535*760c253cSXin Li        self.assertEqual(self.result.keyvals, {"Total": 10, "retval": 0})
1536*760c253cSXin Li
1537*760c253cSXin Li        # Test 2
1538*760c253cSXin Li        self.result.retval = 1
1539*760c253cSXin Li        self.result.ProcessResults()
1540*760c253cSXin Li        self.assertEqual(len(self.result.keyvals), 2)
1541*760c253cSXin Li        self.assertEqual(self.result.keyvals, {"Total": 10, "retval": 1})
1542*760c253cSXin Li
1543*760c253cSXin Li        # Test 3
1544*760c253cSXin Li        self.result.cwp_dso = "chrome"
1545*760c253cSXin Li        self.result.retval = 0
1546*760c253cSXin Li        self.result.GetSamples = FakeGetSamples
1547*760c253cSXin Li        self.result.ProcessResults()
1548*760c253cSXin Li        self.assertEqual(len(self.result.keyvals), 3)
1549*760c253cSXin Li        self.assertEqual(
1550*760c253cSXin Li            self.result.keyvals,
1551*760c253cSXin Li            {"Total": 10, "samples": (1, "samples"), "retval": 0},
1552*760c253cSXin Li        )
1553*760c253cSXin Li
1554*760c253cSXin Li        # Test 4. Parse output of benchmarks with multiple sotries in histogram
1555*760c253cSXin Li        # format
1556*760c253cSXin Li        self.result.suite = "telemetry_Crosperf"
1557*760c253cSXin Li        self.result.results_file = [tempfile.mkdtemp() + "/histograms.json"]
1558*760c253cSXin Li        with open(self.result.results_file[0], "w", encoding="utf-8") as f:
1559*760c253cSXin Li            f.write(HISTOGRAMSET)
1560*760c253cSXin Li        self.result.ProcessResults()
1561*760c253cSXin Li        shutil.rmtree(os.path.dirname(self.result.results_file[0]))
1562*760c253cSXin Li        # Verify the summary for the story is correct
1563*760c253cSXin Li        self.assertEqual(
1564*760c253cSXin Li            self.result.keyvals["timeToFirstContentfulPaint__typical"],
1565*760c253cSXin Li            [880.000, "ms_smallerIsBetter"],
1566*760c253cSXin Li        )
1567*760c253cSXin Li        # Veirfy the summary for a certain stroy tag is correct
1568*760c253cSXin Li        self.assertEqual(
1569*760c253cSXin Li            self.result.keyvals[
1570*760c253cSXin Li                "timeToFirstContentfulPaint__cache_temperature:cold"
1571*760c253cSXin Li            ],
1572*760c253cSXin Li            [1000.000, "ms_smallerIsBetter"],
1573*760c253cSXin Li        )
1574*760c253cSXin Li        self.assertEqual(
1575*760c253cSXin Li            self.result.keyvals[
1576*760c253cSXin Li                "timeToFirstContentfulPaint__cache_temperature:warm"
1577*760c253cSXin Li            ],
1578*760c253cSXin Li            [800.000, "ms_smallerIsBetter"],
1579*760c253cSXin Li        )
1580*760c253cSXin Li
1581*760c253cSXin Li    @mock.patch.object(Result, "ProcessCpustatsResults")
1582*760c253cSXin Li    @mock.patch.object(Result, "ProcessTurbostatResults")
1583*760c253cSXin Li    def test_process_results_with_turbostat_log(
1584*760c253cSXin Li        self, mock_proc_turbo, mock_proc_cpustats
1585*760c253cSXin Li    ):
1586*760c253cSXin Li        self.result.GetKeyvals = self.FakeGetKeyvals
1587*760c253cSXin Li
1588*760c253cSXin Li        self.result.retval = 0
1589*760c253cSXin Li        self.result.turbostat_log_file = "/tmp/turbostat.log"
1590*760c253cSXin Li        mock_proc_turbo.return_value = {
1591*760c253cSXin Li            "cpufreq": {"all": [1, 2, 3]},
1592*760c253cSXin Li            "cputemp": {"all": [5.0, 6.0, 7.0]},
1593*760c253cSXin Li        }
1594*760c253cSXin Li        self.result.ProcessResults()
1595*760c253cSXin Li        mock_proc_turbo.assert_has_calls([mock.call()])
1596*760c253cSXin Li        mock_proc_cpustats.assert_not_called()
1597*760c253cSXin Li        self.assertEqual(len(self.result.keyvals), 8)
1598*760c253cSXin Li        self.assertEqual(
1599*760c253cSXin Li            self.result.keyvals,
1600*760c253cSXin Li            {
1601*760c253cSXin Li                "Total": 10,
1602*760c253cSXin Li                "cpufreq_all_avg": 2,
1603*760c253cSXin Li                "cpufreq_all_max": 3,
1604*760c253cSXin Li                "cpufreq_all_min": 1,
1605*760c253cSXin Li                "cputemp_all_avg": 6.0,
1606*760c253cSXin Li                "cputemp_all_min": 5.0,
1607*760c253cSXin Li                "cputemp_all_max": 7.0,
1608*760c253cSXin Li                "retval": 0,
1609*760c253cSXin Li            },
1610*760c253cSXin Li        )
1611*760c253cSXin Li
1612*760c253cSXin Li    @mock.patch.object(Result, "ProcessCpustatsResults")
1613*760c253cSXin Li    @mock.patch.object(Result, "ProcessTurbostatResults")
1614*760c253cSXin Li    def test_process_results_with_cpustats_log(
1615*760c253cSXin Li        self, mock_proc_turbo, mock_proc_cpustats
1616*760c253cSXin Li    ):
1617*760c253cSXin Li        self.result.GetKeyvals = self.FakeGetKeyvals
1618*760c253cSXin Li
1619*760c253cSXin Li        self.result.retval = 0
1620*760c253cSXin Li        self.result.cpustats_log_file = "/tmp/cpustats.log"
1621*760c253cSXin Li        mock_proc_cpustats.return_value = {
1622*760c253cSXin Li            "cpufreq": {"cpu0": [100, 100, 100], "cpu1": [4, 5, 6]},
1623*760c253cSXin Li            "cputemp": {
1624*760c253cSXin Li                "little": [20.2, 20.2, 20.2],
1625*760c253cSXin Li                "big": [55.2, 66.1, 77.3],
1626*760c253cSXin Li            },
1627*760c253cSXin Li        }
1628*760c253cSXin Li        self.result.ProcessResults()
1629*760c253cSXin Li        mock_proc_turbo.assert_not_called()
1630*760c253cSXin Li        mock_proc_cpustats.assert_has_calls([mock.call()])
1631*760c253cSXin Li        self.assertEqual(len(self.result.keyvals), 10)
1632*760c253cSXin Li        self.assertEqual(
1633*760c253cSXin Li            self.result.keyvals,
1634*760c253cSXin Li            {
1635*760c253cSXin Li                "Total": 10,
1636*760c253cSXin Li                "cpufreq_cpu0_avg": 100,
1637*760c253cSXin Li                "cpufreq_cpu1_avg": 5,
1638*760c253cSXin Li                "cpufreq_cpu1_max": 6,
1639*760c253cSXin Li                "cpufreq_cpu1_min": 4,
1640*760c253cSXin Li                "cputemp_big_avg": 66.2,
1641*760c253cSXin Li                "cputemp_big_max": 77.3,
1642*760c253cSXin Li                "cputemp_big_min": 55.2,
1643*760c253cSXin Li                "cputemp_little_avg": 20.2,
1644*760c253cSXin Li                "retval": 0,
1645*760c253cSXin Li            },
1646*760c253cSXin Li        )
1647*760c253cSXin Li
1648*760c253cSXin Li    @mock.patch.object(Result, "ProcessCpustatsResults")
1649*760c253cSXin Li    @mock.patch.object(Result, "ProcessTurbostatResults")
1650*760c253cSXin Li    def test_process_results_with_turbostat_and_cpustats_logs(
1651*760c253cSXin Li        self, mock_proc_turbo, mock_proc_cpustats
1652*760c253cSXin Li    ):
1653*760c253cSXin Li        self.result.GetKeyvals = self.FakeGetKeyvals
1654*760c253cSXin Li
1655*760c253cSXin Li        self.result.retval = 0
1656*760c253cSXin Li        self.result.turbostat_log_file = "/tmp/turbostat.log"
1657*760c253cSXin Li        self.result.cpustats_log_file = "/tmp/cpustats.log"
1658*760c253cSXin Li        mock_proc_turbo.return_value = {
1659*760c253cSXin Li            "cpufreq": {"all": [1, 2, 3]},
1660*760c253cSXin Li            "cputemp": {"all": [5.0, 6.0, 7.0]},
1661*760c253cSXin Li        }
1662*760c253cSXin Li        self.result.ProcessResults()
1663*760c253cSXin Li        mock_proc_turbo.assert_has_calls([mock.call()])
1664*760c253cSXin Li        mock_proc_cpustats.assert_not_called()
1665*760c253cSXin Li        self.assertEqual(len(self.result.keyvals), 8)
1666*760c253cSXin Li        self.assertEqual(
1667*760c253cSXin Li            self.result.keyvals,
1668*760c253cSXin Li            {
1669*760c253cSXin Li                "Total": 10,
1670*760c253cSXin Li                "cpufreq_all_avg": 2,
1671*760c253cSXin Li                "cpufreq_all_max": 3,
1672*760c253cSXin Li                "cpufreq_all_min": 1,
1673*760c253cSXin Li                "cputemp_all_avg": 6.0,
1674*760c253cSXin Li                "cputemp_all_min": 5.0,
1675*760c253cSXin Li                "cputemp_all_max": 7.0,
1676*760c253cSXin Li                "retval": 0,
1677*760c253cSXin Li            },
1678*760c253cSXin Li        )
1679*760c253cSXin Li
1680*760c253cSXin Li    @mock.patch.object(Result, "ProcessCpustatsResults")
1681*760c253cSXin Li    @mock.patch.object(Result, "ProcessTurbostatResults")
1682*760c253cSXin Li    def test_process_results_without_cpu_data(
1683*760c253cSXin Li        self, mock_proc_turbo, mock_proc_cpustats
1684*760c253cSXin Li    ):
1685*760c253cSXin Li        self.result.GetKeyvals = self.FakeGetKeyvals
1686*760c253cSXin Li
1687*760c253cSXin Li        self.result.retval = 0
1688*760c253cSXin Li        self.result.turbostat_log_file = ""
1689*760c253cSXin Li        self.result.cpustats_log_file = ""
1690*760c253cSXin Li        self.result.ProcessResults()
1691*760c253cSXin Li        mock_proc_turbo.assert_not_called()
1692*760c253cSXin Li        mock_proc_cpustats.assert_not_called()
1693*760c253cSXin Li        self.assertEqual(len(self.result.keyvals), 2)
1694*760c253cSXin Li        self.assertEqual(self.result.keyvals, {"Total": 10, "retval": 0})
1695*760c253cSXin Li
1696*760c253cSXin Li    @mock.patch.object(misc, "GetInsideChrootPath")
1697*760c253cSXin Li    @mock.patch.object(
1698*760c253cSXin Li        command_executer.CommandExecuter, "ChrootRunCommandWOutput"
1699*760c253cSXin Li    )
1700*760c253cSXin Li    def test_populate_from_cache_dir(self, mock_runchrootcmd, mock_getpath):
1701*760c253cSXin Li        # pylint: disable=redefined-builtin
1702*760c253cSXin Li        def FakeMkdtemp(dir=None):
1703*760c253cSXin Li            if dir:
1704*760c253cSXin Li                pass
1705*760c253cSXin Li            return self.tmpdir
1706*760c253cSXin Li
1707*760c253cSXin Li        def FakeGetSamples():
1708*760c253cSXin Li            return [1, "samples"]
1709*760c253cSXin Li
1710*760c253cSXin Li        current_path = os.getcwd()
1711*760c253cSXin Li        cache_dir = os.path.join(current_path, "test_cache/test_input")
1712*760c253cSXin Li        self.result.ce = command_executer.GetCommandExecuter(
1713*760c253cSXin Li            log_level="average"
1714*760c253cSXin Li        )
1715*760c253cSXin Li        self.result.ce.ChrootRunCommandWOutput = mock_runchrootcmd
1716*760c253cSXin Li        mock_runchrootcmd.return_value = [
1717*760c253cSXin Li            "",
1718*760c253cSXin Li            ("%s,PASS\n%s/\telemetry_Crosperf,PASS\n") % (TMP_DIR1, TMP_DIR1),
1719*760c253cSXin Li            "",
1720*760c253cSXin Li        ]
1721*760c253cSXin Li        mock_getpath.return_value = TMP_DIR1
1722*760c253cSXin Li        self.tmpdir = tempfile.mkdtemp()
1723*760c253cSXin Li        save_real_mkdtemp = tempfile.mkdtemp
1724*760c253cSXin Li        tempfile.mkdtemp = FakeMkdtemp
1725*760c253cSXin Li
1726*760c253cSXin Li        self.result.PopulateFromCacheDir(
1727*760c253cSXin Li            cache_dir, "sunspider", "telemetry_Crosperf", ""
1728*760c253cSXin Li        )
1729*760c253cSXin Li        self.assertEqual(
1730*760c253cSXin Li            self.result.keyvals,
1731*760c253cSXin Li            {
1732*760c253cSXin Li                "Total__Total": [444.0, "ms"],
1733*760c253cSXin Li                "regexp-dna__regexp-dna": [16.2, "ms"],
1734*760c253cSXin Li                "telemetry_page_measurement_results__num_failed": [
1735*760c253cSXin Li                    0,
1736*760c253cSXin Li                    "count",
1737*760c253cSXin Li                ],
1738*760c253cSXin Li                "telemetry_page_measurement_results__num_errored": [
1739*760c253cSXin Li                    0,
1740*760c253cSXin Li                    "count",
1741*760c253cSXin Li                ],
1742*760c253cSXin Li                "string-fasta__string-fasta": [23.2, "ms"],
1743*760c253cSXin Li                "crypto-sha1__crypto-sha1": [11.6, "ms"],
1744*760c253cSXin Li                "bitops-3bit-bits-in-byte__bitops-3bit-bits-in-byte": [
1745*760c253cSXin Li                    3.2,
1746*760c253cSXin Li                    "ms",
1747*760c253cSXin Li                ],
1748*760c253cSXin Li                "access-nsieve__access-nsieve": [7.9, "ms"],
1749*760c253cSXin Li                "bitops-nsieve-bits__bitops-nsieve-bits": [9.4, "ms"],
1750*760c253cSXin Li                "string-validate-input__string-validate-input": [19.3, "ms"],
1751*760c253cSXin Li                "3d-raytrace__3d-raytrace": [24.7, "ms"],
1752*760c253cSXin Li                "3d-cube__3d-cube": [28.0, "ms"],
1753*760c253cSXin Li                "string-unpack-code__string-unpack-code": [46.7, "ms"],
1754*760c253cSXin Li                "date-format-tofte__date-format-tofte": [26.3, "ms"],
1755*760c253cSXin Li                "math-partial-sums__math-partial-sums": [22.0, "ms"],
1756*760c253cSXin Li                "\telemetry_Crosperf": ["PASS", ""],
1757*760c253cSXin Li                "crypto-aes__crypto-aes": [15.2, "ms"],
1758*760c253cSXin Li                "bitops-bitwise-and__bitops-bitwise-and": [8.4, "ms"],
1759*760c253cSXin Li                "crypto-md5__crypto-md5": [10.5, "ms"],
1760*760c253cSXin Li                "string-tagcloud__string-tagcloud": [52.8, "ms"],
1761*760c253cSXin Li                "access-nbody__access-nbody": [8.5, "ms"],
1762*760c253cSXin Li                "retval": 0,
1763*760c253cSXin Li                "math-spectral-norm__math-spectral-norm": [6.6, "ms"],
1764*760c253cSXin Li                "math-cordic__math-cordic": [8.7, "ms"],
1765*760c253cSXin Li                "access-binary-trees__access-binary-trees": [4.5, "ms"],
1766*760c253cSXin Li                "controlflow-recursive__controlflow-recursive": [4.4, "ms"],
1767*760c253cSXin Li                "access-fannkuch__access-fannkuch": [17.8, "ms"],
1768*760c253cSXin Li                "string-base64__string-base64": [16.0, "ms"],
1769*760c253cSXin Li                "date-format-xparb__date-format-xparb": [20.9, "ms"],
1770*760c253cSXin Li                "3d-morph__3d-morph": [22.1, "ms"],
1771*760c253cSXin Li                "bitops-bits-in-byte__bitops-bits-in-byte": [9.1, "ms"],
1772*760c253cSXin Li            },
1773*760c253cSXin Li        )
1774*760c253cSXin Li
1775*760c253cSXin Li        self.result.GetSamples = FakeGetSamples
1776*760c253cSXin Li        self.result.PopulateFromCacheDir(
1777*760c253cSXin Li            cache_dir, "sunspider", "telemetry_Crosperf", "chrome"
1778*760c253cSXin Li        )
1779*760c253cSXin Li        self.assertEqual(
1780*760c253cSXin Li            self.result.keyvals,
1781*760c253cSXin Li            {
1782*760c253cSXin Li                "Total__Total": [444.0, "ms"],
1783*760c253cSXin Li                "regexp-dna__regexp-dna": [16.2, "ms"],
1784*760c253cSXin Li                "telemetry_page_measurement_results__num_failed": [
1785*760c253cSXin Li                    0,
1786*760c253cSXin Li                    "count",
1787*760c253cSXin Li                ],
1788*760c253cSXin Li                "telemetry_page_measurement_results__num_errored": [
1789*760c253cSXin Li                    0,
1790*760c253cSXin Li                    "count",
1791*760c253cSXin Li                ],
1792*760c253cSXin Li                "string-fasta__string-fasta": [23.2, "ms"],
1793*760c253cSXin Li                "crypto-sha1__crypto-sha1": [11.6, "ms"],
1794*760c253cSXin Li                "bitops-3bit-bits-in-byte__bitops-3bit-bits-in-byte": [
1795*760c253cSXin Li                    3.2,
1796*760c253cSXin Li                    "ms",
1797*760c253cSXin Li                ],
1798*760c253cSXin Li                "access-nsieve__access-nsieve": [7.9, "ms"],
1799*760c253cSXin Li                "bitops-nsieve-bits__bitops-nsieve-bits": [9.4, "ms"],
1800*760c253cSXin Li                "string-validate-input__string-validate-input": [19.3, "ms"],
1801*760c253cSXin Li                "3d-raytrace__3d-raytrace": [24.7, "ms"],
1802*760c253cSXin Li                "3d-cube__3d-cube": [28.0, "ms"],
1803*760c253cSXin Li                "string-unpack-code__string-unpack-code": [46.7, "ms"],
1804*760c253cSXin Li                "date-format-tofte__date-format-tofte": [26.3, "ms"],
1805*760c253cSXin Li                "math-partial-sums__math-partial-sums": [22.0, "ms"],
1806*760c253cSXin Li                "\telemetry_Crosperf": ["PASS", ""],
1807*760c253cSXin Li                "crypto-aes__crypto-aes": [15.2, "ms"],
1808*760c253cSXin Li                "bitops-bitwise-and__bitops-bitwise-and": [8.4, "ms"],
1809*760c253cSXin Li                "crypto-md5__crypto-md5": [10.5, "ms"],
1810*760c253cSXin Li                "string-tagcloud__string-tagcloud": [52.8, "ms"],
1811*760c253cSXin Li                "access-nbody__access-nbody": [8.5, "ms"],
1812*760c253cSXin Li                "retval": 0,
1813*760c253cSXin Li                "math-spectral-norm__math-spectral-norm": [6.6, "ms"],
1814*760c253cSXin Li                "math-cordic__math-cordic": [8.7, "ms"],
1815*760c253cSXin Li                "access-binary-trees__access-binary-trees": [4.5, "ms"],
1816*760c253cSXin Li                "controlflow-recursive__controlflow-recursive": [4.4, "ms"],
1817*760c253cSXin Li                "access-fannkuch__access-fannkuch": [17.8, "ms"],
1818*760c253cSXin Li                "string-base64__string-base64": [16.0, "ms"],
1819*760c253cSXin Li                "date-format-xparb__date-format-xparb": [20.9, "ms"],
1820*760c253cSXin Li                "3d-morph__3d-morph": [22.1, "ms"],
1821*760c253cSXin Li                "bitops-bits-in-byte__bitops-bits-in-byte": [9.1, "ms"],
1822*760c253cSXin Li                "samples": [1, "samples"],
1823*760c253cSXin Li            },
1824*760c253cSXin Li        )
1825*760c253cSXin Li
1826*760c253cSXin Li        # Clean up after test.
1827*760c253cSXin Li        tempfile.mkdtemp = save_real_mkdtemp
1828*760c253cSXin Li        command = "rm -Rf %s" % self.tmpdir
1829*760c253cSXin Li        self.result.ce.RunCommand(command)
1830*760c253cSXin Li
1831*760c253cSXin Li    @mock.patch.object(misc, "GetRoot")
1832*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommand")
1833*760c253cSXin Li    def test_cleanup(self, mock_runcmd, mock_getroot):
1834*760c253cSXin Li        # Test 1. 'rm_chroot_tmp' is True; self.results_dir exists;
1835*760c253cSXin Li        # self.temp_dir exists; results_dir name contains 'test_that_results_'.
1836*760c253cSXin Li        mock_getroot.return_value = [
1837*760c253cSXin Li            "/tmp/tmp_AbcXyz",
1838*760c253cSXin Li            "test_that_results_fake",
1839*760c253cSXin Li        ]
1840*760c253cSXin Li        self.result.ce.RunCommand = mock_runcmd
1841*760c253cSXin Li        self.result.results_dir = "test_results_dir"
1842*760c253cSXin Li        self.result.temp_dir = "testtemp_dir"
1843*760c253cSXin Li        self.result.CleanUp(True)
1844*760c253cSXin Li        self.assertEqual(mock_getroot.call_count, 1)
1845*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 2)
1846*760c253cSXin Li        self.assertEqual(
1847*760c253cSXin Li            mock_runcmd.call_args_list[0][0], ("rm -rf test_results_dir",)
1848*760c253cSXin Li        )
1849*760c253cSXin Li        self.assertEqual(
1850*760c253cSXin Li            mock_runcmd.call_args_list[1][0], ("rm -rf testtemp_dir",)
1851*760c253cSXin Li        )
1852*760c253cSXin Li
1853*760c253cSXin Li        # Test 2. Same, except ath results_dir name does not contain
1854*760c253cSXin Li        # 'test_that_results_'
1855*760c253cSXin Li        mock_getroot.reset_mock()
1856*760c253cSXin Li        mock_runcmd.reset_mock()
1857*760c253cSXin Li        mock_getroot.return_value = ["/tmp/tmp_AbcXyz", "other_results_fake"]
1858*760c253cSXin Li        self.result.ce.RunCommand = mock_runcmd
1859*760c253cSXin Li        self.result.results_dir = "test_results_dir"
1860*760c253cSXin Li        self.result.temp_dir = "testtemp_dir"
1861*760c253cSXin Li        self.result.CleanUp(True)
1862*760c253cSXin Li        self.assertEqual(mock_getroot.call_count, 1)
1863*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 2)
1864*760c253cSXin Li        self.assertEqual(
1865*760c253cSXin Li            mock_runcmd.call_args_list[0][0], ("rm -rf /tmp/tmp_AbcXyz",)
1866*760c253cSXin Li        )
1867*760c253cSXin Li        self.assertEqual(
1868*760c253cSXin Li            mock_runcmd.call_args_list[1][0], ("rm -rf testtemp_dir",)
1869*760c253cSXin Li        )
1870*760c253cSXin Li
1871*760c253cSXin Li        # Test 3. mock_getroot returns nothing; 'rm_chroot_tmp' is False.
1872*760c253cSXin Li        mock_getroot.reset_mock()
1873*760c253cSXin Li        mock_runcmd.reset_mock()
1874*760c253cSXin Li        self.result.CleanUp(False)
1875*760c253cSXin Li        self.assertEqual(mock_getroot.call_count, 0)
1876*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 1)
1877*760c253cSXin Li        self.assertEqual(
1878*760c253cSXin Li            mock_runcmd.call_args_list[0][0], ("rm -rf testtemp_dir",)
1879*760c253cSXin Li        )
1880*760c253cSXin Li
1881*760c253cSXin Li        # Test 4. 'rm_chroot_tmp' is True, but result_dir & temp_dir are None.
1882*760c253cSXin Li        mock_getroot.reset_mock()
1883*760c253cSXin Li        mock_runcmd.reset_mock()
1884*760c253cSXin Li        self.result.results_dir = None
1885*760c253cSXin Li        self.result.temp_dir = None
1886*760c253cSXin Li        self.result.CleanUp(True)
1887*760c253cSXin Li        self.assertEqual(mock_getroot.call_count, 0)
1888*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 0)
1889*760c253cSXin Li
1890*760c253cSXin Li    @mock.patch.object(misc, "GetInsideChrootPath")
1891*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "ChrootRunCommand")
1892*760c253cSXin Li    def test_store_to_cache_dir(self, mock_chrootruncmd, mock_getpath):
1893*760c253cSXin Li        def FakeMkdtemp(directory=""):
1894*760c253cSXin Li            if directory:
1895*760c253cSXin Li                pass
1896*760c253cSXin Li            return self.tmpdir
1897*760c253cSXin Li
1898*760c253cSXin Li        if mock_chrootruncmd or mock_getpath:
1899*760c253cSXin Li            pass
1900*760c253cSXin Li        current_path = os.getcwd()
1901*760c253cSXin Li        cache_dir = os.path.join(current_path, "test_cache/test_output")
1902*760c253cSXin Li
1903*760c253cSXin Li        self.result.ce = command_executer.GetCommandExecuter(
1904*760c253cSXin Li            log_level="average"
1905*760c253cSXin Li        )
1906*760c253cSXin Li        self.result.out = OUTPUT
1907*760c253cSXin Li        self.result.err = error
1908*760c253cSXin Li        self.result.retval = 0
1909*760c253cSXin Li        self.tmpdir = tempfile.mkdtemp()
1910*760c253cSXin Li        if not os.path.exists(self.tmpdir):
1911*760c253cSXin Li            os.makedirs(self.tmpdir)
1912*760c253cSXin Li        self.result.results_dir = os.path.join(os.getcwd(), "test_cache")
1913*760c253cSXin Li        save_real_mkdtemp = tempfile.mkdtemp
1914*760c253cSXin Li        tempfile.mkdtemp = FakeMkdtemp
1915*760c253cSXin Li
1916*760c253cSXin Li        mock_mm = machine_manager.MockMachineManager(
1917*760c253cSXin Li            "/tmp/chromeos_root", 0, "average", ""
1918*760c253cSXin Li        )
1919*760c253cSXin Li        mock_mm.machine_checksum_string[
1920*760c253cSXin Li            "mock_label"
1921*760c253cSXin Li        ] = "fake_machine_checksum123"
1922*760c253cSXin Li
1923*760c253cSXin Li        mock_keylist = ["key1", "key2", "key3"]
1924*760c253cSXin Li        test_flag.SetTestMode(True)
1925*760c253cSXin Li        self.result.StoreToCacheDir(cache_dir, mock_mm, mock_keylist)
1926*760c253cSXin Li
1927*760c253cSXin Li        # Check that the correct things were written to the 'cache'.
1928*760c253cSXin Li        test_dir = os.path.join(os.getcwd(), "test_cache/test_output")
1929*760c253cSXin Li        base_dir = os.path.join(os.getcwd(), "test_cache/compare_output")
1930*760c253cSXin Li        self.assertTrue(os.path.exists(os.path.join(test_dir, "autotest.tbz2")))
1931*760c253cSXin Li        self.assertTrue(os.path.exists(os.path.join(test_dir, "machine.txt")))
1932*760c253cSXin Li        self.assertTrue(
1933*760c253cSXin Li            os.path.exists(os.path.join(test_dir, "results.pickle"))
1934*760c253cSXin Li        )
1935*760c253cSXin Li
1936*760c253cSXin Li        f1 = os.path.join(test_dir, "machine.txt")
1937*760c253cSXin Li        f2 = os.path.join(base_dir, "machine.txt")
1938*760c253cSXin Li        cmd = "diff %s %s" % (f1, f2)
1939*760c253cSXin Li        [_, out, _] = self.result.ce.RunCommandWOutput(cmd)
1940*760c253cSXin Li        self.assertEqual(len(out), 0)
1941*760c253cSXin Li
1942*760c253cSXin Li        f1 = os.path.join(test_dir, "results.pickle")
1943*760c253cSXin Li        f2 = os.path.join(base_dir, "results.pickle")
1944*760c253cSXin Li        with open(f1, "rb") as f:
1945*760c253cSXin Li            f1_obj = pickle.load(f)
1946*760c253cSXin Li        with open(f2, "rb") as f:
1947*760c253cSXin Li            f2_obj = pickle.load(f)
1948*760c253cSXin Li        self.assertEqual(f1_obj, f2_obj)
1949*760c253cSXin Li
1950*760c253cSXin Li        # Clean up after test.
1951*760c253cSXin Li        tempfile.mkdtemp = save_real_mkdtemp
1952*760c253cSXin Li        command = "rm %s/*" % test_dir
1953*760c253cSXin Li        self.result.ce.RunCommand(command)
1954*760c253cSXin Li
1955*760c253cSXin Li
1956*760c253cSXin LiTELEMETRY_RESULT_KEYVALS = {
1957*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1958*760c253cSXin Li    "math-cordic (ms)": "11.4",
1959*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1960*760c253cSXin Li    "access-nbody (ms)": "6.9",
1961*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1962*760c253cSXin Li    "access-fannkuch (ms)": "26.3",
1963*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1964*760c253cSXin Li    "math-spectral-norm (ms)": "6.3",
1965*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1966*760c253cSXin Li    "bitops-nsieve-bits (ms)": "9.3",
1967*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1968*760c253cSXin Li    "math-partial-sums (ms)": "32.8",
1969*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1970*760c253cSXin Li    "regexp-dna (ms)": "16.1",
1971*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1972*760c253cSXin Li    "3d-cube (ms)": "42.7",
1973*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1974*760c253cSXin Li    "crypto-md5 (ms)": "10.8",
1975*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1976*760c253cSXin Li    "crypto-sha1 (ms)": "12.4",
1977*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1978*760c253cSXin Li    "string-tagcloud (ms)": "47.2",
1979*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1980*760c253cSXin Li    "string-fasta (ms)": "36.3",
1981*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1982*760c253cSXin Li    "access-binary-trees (ms)": "7.3",
1983*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1984*760c253cSXin Li    "date-format-xparb (ms)": "138.1",
1985*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1986*760c253cSXin Li    "crypto-aes (ms)": "19.2",
1987*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1988*760c253cSXin Li    "Total (ms)": "656.5",
1989*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1990*760c253cSXin Li    "string-base64 (ms)": "17.5",
1991*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1992*760c253cSXin Li    "string-validate-input (ms)": "24.8",
1993*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1994*760c253cSXin Li    "3d-raytrace (ms)": "28.7",
1995*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1996*760c253cSXin Li    "controlflow-recursive (ms)": "5.3",
1997*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
1998*760c253cSXin Li    "bitops-bits-in-byte (ms)": "9.8",
1999*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
2000*760c253cSXin Li    "3d-morph (ms)": "50.2",
2001*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
2002*760c253cSXin Li    "bitops-bitwise-and (ms)": "8.8",
2003*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
2004*760c253cSXin Li    "access-nsieve (ms)": "8.6",
2005*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
2006*760c253cSXin Li    "date-format-tofte (ms)": "31.2",
2007*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
2008*760c253cSXin Li    "bitops-3bit-bits-in-byte (ms)": "3.5",
2009*760c253cSXin Li    "retval": 0,
2010*760c253cSXin Li    "http://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html "
2011*760c253cSXin Li    "string-unpack-code (ms)": "45.0",
2012*760c253cSXin Li}
2013*760c253cSXin Li
2014*760c253cSXin LiPURE_TELEMETRY_OUTPUT = """
2015*760c253cSXin Lipage_name,3d-cube (ms),3d-morph (ms),3d-raytrace (ms),Total (ms),access-binary-trees (ms),access-fannkuch (ms),access-nbody (ms),access-nsieve (ms),bitops-3bit-bits-in-byte (ms),bitops-bits-in-byte (ms),bitops-bitwise-and (ms),bitops-nsieve-bits (ms),controlflow-recursive (ms),crypto-aes (ms),crypto-md5 (ms),crypto-sha1 (ms),date-format-tofte (ms),date-format-xparb (ms),math-cordic (ms),math-partial-sums (ms),math-spectral-norm (ms),regexp-dna (ms),string-base64 (ms),string-fasta (ms),string-tagcloud (ms),string-unpack-code (ms),string-validate-input (ms)\r\nhttp://www.webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html,42.7,50.2,28.7,656.5,7.3,26.3,6.9,8.6,3.5,9.8,8.8,9.3,5.3,19.2,10.8,12.4,31.2,138.1,11.4,32.8,6.3,16.1,17.5,36.3,47.2,45.0,24.8\r
2016*760c253cSXin Li"""
2017*760c253cSXin Li
2018*760c253cSXin Li
2019*760c253cSXin Liclass TelemetryResultTest(unittest.TestCase):
2020*760c253cSXin Li    """Telemetry result test."""
2021*760c253cSXin Li
2022*760c253cSXin Li    def __init__(self, *args, **kwargs):
2023*760c253cSXin Li        super(TelemetryResultTest, self).__init__(*args, **kwargs)
2024*760c253cSXin Li        self.callFakeProcessResults = False
2025*760c253cSXin Li        self.result = None
2026*760c253cSXin Li        self.mock_logger = mock.Mock(spec=logger.Logger)
2027*760c253cSXin Li        self.mock_cmd_exec = mock.Mock(spec=command_executer.CommandExecuter)
2028*760c253cSXin Li        self.mock_label = MockLabel(
2029*760c253cSXin Li            "mock_label",
2030*760c253cSXin Li            "build",
2031*760c253cSXin Li            "chromeos_image",
2032*760c253cSXin Li            "autotest_dir",
2033*760c253cSXin Li            "debug_dir",
2034*760c253cSXin Li            "/tmp",
2035*760c253cSXin Li            "lumpy",
2036*760c253cSXin Li            "remote",
2037*760c253cSXin Li            "image_args",
2038*760c253cSXin Li            "cache_dir",
2039*760c253cSXin Li            "average",
2040*760c253cSXin Li            "gcc",
2041*760c253cSXin Li            False,
2042*760c253cSXin Li            None,
2043*760c253cSXin Li        )
2044*760c253cSXin Li        self.mock_machine = machine_manager.MockCrosMachine(
2045*760c253cSXin Li            "falco.cros", "/tmp/chromeos", "average"
2046*760c253cSXin Li        )
2047*760c253cSXin Li
2048*760c253cSXin Li    def test_populate_from_run(self):
2049*760c253cSXin Li        def FakeProcessResults():
2050*760c253cSXin Li            self.callFakeProcessResults = True
2051*760c253cSXin Li
2052*760c253cSXin Li        self.callFakeProcessResults = False
2053*760c253cSXin Li        self.result = TelemetryResult(
2054*760c253cSXin Li            self.mock_logger, self.mock_label, "average", self.mock_cmd_exec
2055*760c253cSXin Li        )
2056*760c253cSXin Li        self.result.ProcessResults = FakeProcessResults
2057*760c253cSXin Li        self.result.PopulateFromRun(
2058*760c253cSXin Li            OUTPUT, error, 3, "fake_test", "telemetry_Crosperf", ""
2059*760c253cSXin Li        )
2060*760c253cSXin Li        self.assertTrue(self.callFakeProcessResults)
2061*760c253cSXin Li        self.assertEqual(self.result.out, OUTPUT)
2062*760c253cSXin Li        self.assertEqual(self.result.err, error)
2063*760c253cSXin Li        self.assertEqual(self.result.retval, 3)
2064*760c253cSXin Li
2065*760c253cSXin Li    def test_populate_from_cache_dir_and_process_results(self):
2066*760c253cSXin Li        self.result = TelemetryResult(
2067*760c253cSXin Li            self.mock_logger, self.mock_label, "average", self.mock_machine
2068*760c253cSXin Li        )
2069*760c253cSXin Li        current_path = os.getcwd()
2070*760c253cSXin Li        cache_dir = os.path.join(
2071*760c253cSXin Li            current_path, "test_cache/test_puretelemetry_input"
2072*760c253cSXin Li        )
2073*760c253cSXin Li        self.result.PopulateFromCacheDir(cache_dir, "", "", "")
2074*760c253cSXin Li        self.assertEqual(self.result.out.strip(), PURE_TELEMETRY_OUTPUT.strip())
2075*760c253cSXin Li        self.assertEqual(self.result.err, "")
2076*760c253cSXin Li        self.assertEqual(self.result.retval, 0)
2077*760c253cSXin Li        self.assertEqual(self.result.keyvals, TELEMETRY_RESULT_KEYVALS)
2078*760c253cSXin Li
2079*760c253cSXin Li
2080*760c253cSXin Liclass ResultsCacheTest(unittest.TestCase):
2081*760c253cSXin Li    """Resultcache test class."""
2082*760c253cSXin Li
2083*760c253cSXin Li    def __init__(self, *args, **kwargs):
2084*760c253cSXin Li        super(ResultsCacheTest, self).__init__(*args, **kwargs)
2085*760c253cSXin Li        self.fakeCacheReturnResult = None
2086*760c253cSXin Li        self.mock_logger = mock.Mock(spec=logger.Logger)
2087*760c253cSXin Li        self.mock_label = MockLabel(
2088*760c253cSXin Li            "mock_label",
2089*760c253cSXin Li            "build",
2090*760c253cSXin Li            "chromeos_image",
2091*760c253cSXin Li            "autotest_dir",
2092*760c253cSXin Li            "debug_dir",
2093*760c253cSXin Li            "/tmp",
2094*760c253cSXin Li            "lumpy",
2095*760c253cSXin Li            "remote",
2096*760c253cSXin Li            "image_args",
2097*760c253cSXin Li            "cache_dir",
2098*760c253cSXin Li            "average",
2099*760c253cSXin Li            "gcc",
2100*760c253cSXin Li            False,
2101*760c253cSXin Li            None,
2102*760c253cSXin Li        )
2103*760c253cSXin Li
2104*760c253cSXin Li    def setUp(self):
2105*760c253cSXin Li        self.results_cache = ResultsCache()
2106*760c253cSXin Li
2107*760c253cSXin Li        mock_machine = machine_manager.MockCrosMachine(
2108*760c253cSXin Li            "falco.cros", "/tmp/chromeos", "average"
2109*760c253cSXin Li        )
2110*760c253cSXin Li
2111*760c253cSXin Li        mock_mm = machine_manager.MockMachineManager(
2112*760c253cSXin Li            "/tmp/chromeos_root", 0, "average", ""
2113*760c253cSXin Li        )
2114*760c253cSXin Li        mock_mm.machine_checksum_string[
2115*760c253cSXin Li            "mock_label"
2116*760c253cSXin Li        ] = "fake_machine_checksum123"
2117*760c253cSXin Li
2118*760c253cSXin Li        self.results_cache.Init(
2119*760c253cSXin Li            self.mock_label.chromeos_image,
2120*760c253cSXin Li            self.mock_label.chromeos_root,
2121*760c253cSXin Li            "sunspider",
2122*760c253cSXin Li            1,  # benchmark_run.iteration,
2123*760c253cSXin Li            "",  # benchmark_run.test_args,
2124*760c253cSXin Li            "",  # benchmark_run.profiler_args,
2125*760c253cSXin Li            mock_mm,
2126*760c253cSXin Li            mock_machine,
2127*760c253cSXin Li            self.mock_label.board,
2128*760c253cSXin Li            [
2129*760c253cSXin Li                CacheConditions.CACHE_FILE_EXISTS,
2130*760c253cSXin Li                CacheConditions.CHECKSUMS_MATCH,
2131*760c253cSXin Li            ],
2132*760c253cSXin Li            self.mock_logger,
2133*760c253cSXin Li            "average",
2134*760c253cSXin Li            self.mock_label,
2135*760c253cSXin Li            "",  # benchmark_run.share_cache
2136*760c253cSXin Li            "telemetry_Crosperf",
2137*760c253cSXin Li            True,  # benchmark_run.show_all_results
2138*760c253cSXin Li            False,  # benchmark_run.run_local
2139*760c253cSXin Li            "",
2140*760c253cSXin Li        )  # benchmark_run.cwp_dso
2141*760c253cSXin Li
2142*760c253cSXin Li    @mock.patch.object(image_checksummer.ImageChecksummer, "Checksum")
2143*760c253cSXin Li    def test_get_cache_dir_for_write(self, mock_checksum):
2144*760c253cSXin Li        def FakeGetMachines(label):
2145*760c253cSXin Li            if label:
2146*760c253cSXin Li                pass
2147*760c253cSXin Li            m1 = machine_manager.MockCrosMachine(
2148*760c253cSXin Li                "lumpy1.cros", self.results_cache.chromeos_root, "average"
2149*760c253cSXin Li            )
2150*760c253cSXin Li            m2 = machine_manager.MockCrosMachine(
2151*760c253cSXin Li                "lumpy2.cros", self.results_cache.chromeos_root, "average"
2152*760c253cSXin Li            )
2153*760c253cSXin Li            return [m1, m2]
2154*760c253cSXin Li
2155*760c253cSXin Li        mock_checksum.return_value = "FakeImageChecksumabc123"
2156*760c253cSXin Li        self.results_cache.machine_manager.GetMachines = FakeGetMachines
2157*760c253cSXin Li        self.results_cache.machine_manager.machine_checksum[
2158*760c253cSXin Li            "mock_label"
2159*760c253cSXin Li        ] = "FakeMachineChecksumabc987"
2160*760c253cSXin Li        # Based on the label, benchmark and machines, get the directory in which
2161*760c253cSXin Li        # to store the cache information for this test run.
2162*760c253cSXin Li        result_path = self.results_cache.GetCacheDirForWrite()
2163*760c253cSXin Li        # Verify that the returned directory is correct (since the label
2164*760c253cSXin Li        # contained a cache_dir, named 'cache_dir', that's what is expected in
2165*760c253cSXin Li        # the result, rather than '~/cros_scratch').
2166*760c253cSXin Li        comp_path = os.path.join(
2167*760c253cSXin Li            os.getcwd(),
2168*760c253cSXin Li            "cache_dir/54524606abaae4fdf7b02f49f7ae7127_"
2169*760c253cSXin Li            "sunspider_1_fda29412ceccb72977516c4785d08e2c_"
2170*760c253cSXin Li            "FakeImageChecksumabc123_FakeMachineChecksum"
2171*760c253cSXin Li            "abc987__6",
2172*760c253cSXin Li        )
2173*760c253cSXin Li        self.assertEqual(result_path, comp_path)
2174*760c253cSXin Li
2175*760c253cSXin Li    def test_form_cache_dir(self):
2176*760c253cSXin Li        # This is very similar to the previous test (FormCacheDir is called
2177*760c253cSXin Li        # from GetCacheDirForWrite).
2178*760c253cSXin Li        cache_key_list = (
2179*760c253cSXin Li            "54524606abaae4fdf7b02f49f7ae7127",
2180*760c253cSXin Li            "sunspider",
2181*760c253cSXin Li            "1",
2182*760c253cSXin Li            "7215ee9c7d9dc229d2921a40e899ec5f",
2183*760c253cSXin Li            "FakeImageChecksumabc123",
2184*760c253cSXin Li            "*",
2185*760c253cSXin Li            "*",
2186*760c253cSXin Li            "6",
2187*760c253cSXin Li        )
2188*760c253cSXin Li        path = self.results_cache.FormCacheDir(cache_key_list)
2189*760c253cSXin Li        self.assertEqual(len(path), 1)
2190*760c253cSXin Li        path1 = path[0]
2191*760c253cSXin Li        test_dirname = (
2192*760c253cSXin Li            "54524606abaae4fdf7b02f49f7ae7127_sunspider_1_7215ee9"
2193*760c253cSXin Li            "c7d9dc229d2921a40e899ec5f_FakeImageChecksumabc123_*_*_6"
2194*760c253cSXin Li        )
2195*760c253cSXin Li        comp_path = os.path.join(os.getcwd(), "cache_dir", test_dirname)
2196*760c253cSXin Li        self.assertEqual(path1, comp_path)
2197*760c253cSXin Li
2198*760c253cSXin Li    @mock.patch.object(image_checksummer.ImageChecksummer, "Checksum")
2199*760c253cSXin Li    def test_get_cache_key_list(self, mock_checksum):
2200*760c253cSXin Li        # This tests the mechanism that generates the various pieces of the
2201*760c253cSXin Li        # cache directory name, based on various conditions.
2202*760c253cSXin Li
2203*760c253cSXin Li        def FakeGetMachines(label):
2204*760c253cSXin Li            if label:
2205*760c253cSXin Li                pass
2206*760c253cSXin Li            m1 = machine_manager.MockCrosMachine(
2207*760c253cSXin Li                "lumpy1.cros", self.results_cache.chromeos_root, "average"
2208*760c253cSXin Li            )
2209*760c253cSXin Li            m2 = machine_manager.MockCrosMachine(
2210*760c253cSXin Li                "lumpy2.cros", self.results_cache.chromeos_root, "average"
2211*760c253cSXin Li            )
2212*760c253cSXin Li            return [m1, m2]
2213*760c253cSXin Li
2214*760c253cSXin Li        mock_checksum.return_value = "FakeImageChecksumabc123"
2215*760c253cSXin Li        self.results_cache.machine_manager.GetMachines = FakeGetMachines
2216*760c253cSXin Li        self.results_cache.machine_manager.machine_checksum[
2217*760c253cSXin Li            "mock_label"
2218*760c253cSXin Li        ] = "FakeMachineChecksumabc987"
2219*760c253cSXin Li
2220*760c253cSXin Li        # Test 1. Generating cache name for reading (not writing).
2221*760c253cSXin Li        key_list = self.results_cache.GetCacheKeyList(True)
2222*760c253cSXin Li        self.assertEqual(key_list[0], "*")  # Machine checksum value, for read.
2223*760c253cSXin Li        self.assertEqual(key_list[1], "sunspider")
2224*760c253cSXin Li        self.assertEqual(key_list[2], "1")
2225*760c253cSXin Li        self.assertEqual(key_list[3], "fda29412ceccb72977516c4785d08e2c")
2226*760c253cSXin Li        self.assertEqual(key_list[4], "FakeImageChecksumabc123")
2227*760c253cSXin Li        self.assertEqual(key_list[5], "*")
2228*760c253cSXin Li        self.assertEqual(key_list[6], "*")
2229*760c253cSXin Li        self.assertEqual(key_list[7], "6")
2230*760c253cSXin Li
2231*760c253cSXin Li        # Test 2. Generating cache name for writing, with local image type.
2232*760c253cSXin Li        key_list = self.results_cache.GetCacheKeyList(False)
2233*760c253cSXin Li        self.assertEqual(key_list[0], "54524606abaae4fdf7b02f49f7ae7127")
2234*760c253cSXin Li        self.assertEqual(key_list[1], "sunspider")
2235*760c253cSXin Li        self.assertEqual(key_list[2], "1")
2236*760c253cSXin Li        self.assertEqual(key_list[3], "fda29412ceccb72977516c4785d08e2c")
2237*760c253cSXin Li        self.assertEqual(key_list[4], "FakeImageChecksumabc123")
2238*760c253cSXin Li        self.assertEqual(key_list[5], "FakeMachineChecksumabc987")
2239*760c253cSXin Li        self.assertEqual(key_list[6], "")
2240*760c253cSXin Li        self.assertEqual(key_list[7], "6")
2241*760c253cSXin Li
2242*760c253cSXin Li        # Test 3. Generating cache name for writing, with trybot image type.
2243*760c253cSXin Li        self.results_cache.label.image_type = "trybot"
2244*760c253cSXin Li        key_list = self.results_cache.GetCacheKeyList(False)
2245*760c253cSXin Li        self.assertEqual(key_list[0], "54524606abaae4fdf7b02f49f7ae7127")
2246*760c253cSXin Li        self.assertEqual(key_list[3], "fda29412ceccb72977516c4785d08e2c")
2247*760c253cSXin Li        self.assertEqual(key_list[4], "54524606abaae4fdf7b02f49f7ae7127")
2248*760c253cSXin Li        self.assertEqual(key_list[5], "FakeMachineChecksumabc987")
2249*760c253cSXin Li
2250*760c253cSXin Li        # Test 4. Generating cache name for writing, with official image type.
2251*760c253cSXin Li        self.results_cache.label.image_type = "official"
2252*760c253cSXin Li        key_list = self.results_cache.GetCacheKeyList(False)
2253*760c253cSXin Li        self.assertEqual(key_list[0], "54524606abaae4fdf7b02f49f7ae7127")
2254*760c253cSXin Li        self.assertEqual(key_list[1], "sunspider")
2255*760c253cSXin Li        self.assertEqual(key_list[2], "1")
2256*760c253cSXin Li        self.assertEqual(key_list[3], "fda29412ceccb72977516c4785d08e2c")
2257*760c253cSXin Li        self.assertEqual(key_list[4], "*")
2258*760c253cSXin Li        self.assertEqual(key_list[5], "FakeMachineChecksumabc987")
2259*760c253cSXin Li        self.assertEqual(key_list[6], "")
2260*760c253cSXin Li        self.assertEqual(key_list[7], "6")
2261*760c253cSXin Li
2262*760c253cSXin Li        # Test 5. Generating cache name for writing, with local image type, and
2263*760c253cSXin Li        # specifying that the image path must match the cached image path.
2264*760c253cSXin Li        self.results_cache.label.image_type = "local"
2265*760c253cSXin Li        self.results_cache.cache_conditions.append(
2266*760c253cSXin Li            CacheConditions.IMAGE_PATH_MATCH
2267*760c253cSXin Li        )
2268*760c253cSXin Li        key_list = self.results_cache.GetCacheKeyList(False)
2269*760c253cSXin Li        self.assertEqual(key_list[0], "54524606abaae4fdf7b02f49f7ae7127")
2270*760c253cSXin Li        self.assertEqual(key_list[3], "fda29412ceccb72977516c4785d08e2c")
2271*760c253cSXin Li        self.assertEqual(key_list[4], "FakeImageChecksumabc123")
2272*760c253cSXin Li        self.assertEqual(key_list[5], "FakeMachineChecksumabc987")
2273*760c253cSXin Li
2274*760c253cSXin Li    @mock.patch.object(command_executer.CommandExecuter, "RunCommand")
2275*760c253cSXin Li    @mock.patch.object(os.path, "isdir")
2276*760c253cSXin Li    @mock.patch.object(Result, "CreateFromCacheHit")
2277*760c253cSXin Li    def test_read_result(self, mock_create, mock_isdir, mock_runcmd):
2278*760c253cSXin Li        self.fakeCacheReturnResult = None
2279*760c253cSXin Li
2280*760c253cSXin Li        def FakeGetCacheDirForRead():
2281*760c253cSXin Li            return self.fakeCacheReturnResult
2282*760c253cSXin Li
2283*760c253cSXin Li        def FakeGetCacheDirForWrite():
2284*760c253cSXin Li            return self.fakeCacheReturnResult
2285*760c253cSXin Li
2286*760c253cSXin Li        mock_cmd_exec = mock.Mock(spec=command_executer.CommandExecuter)
2287*760c253cSXin Li        fake_result = Result(
2288*760c253cSXin Li            self.mock_logger, self.mock_label, "average", mock_cmd_exec
2289*760c253cSXin Li        )
2290*760c253cSXin Li        fake_result.retval = 0
2291*760c253cSXin Li
2292*760c253cSXin Li        # Set up results_cache _GetCacheDirFor{Read,Write} to return
2293*760c253cSXin Li        # self.fakeCacheReturnResult, which is initially None (see above).
2294*760c253cSXin Li        # So initially, no cache dir is returned.
2295*760c253cSXin Li        self.results_cache.GetCacheDirForRead = FakeGetCacheDirForRead
2296*760c253cSXin Li        self.results_cache.GetCacheDirForWrite = FakeGetCacheDirForWrite
2297*760c253cSXin Li
2298*760c253cSXin Li        mock_isdir.return_value = True
2299*760c253cSXin Li        save_cc = [
2300*760c253cSXin Li            CacheConditions.CACHE_FILE_EXISTS,
2301*760c253cSXin Li            CacheConditions.CHECKSUMS_MATCH,
2302*760c253cSXin Li        ]
2303*760c253cSXin Li        self.results_cache.cache_conditions.append(CacheConditions.FALSE)
2304*760c253cSXin Li
2305*760c253cSXin Li        # Test 1. CacheCondition.FALSE, which means do not read from the cache.
2306*760c253cSXin Li        # (force re-running of test).  Result should be None.
2307*760c253cSXin Li        res = self.results_cache.ReadResult()
2308*760c253cSXin Li        self.assertIsNone(res)
2309*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 1)
2310*760c253cSXin Li
2311*760c253cSXin Li        # Test 2. Remove CacheCondition.FALSE. Result should still be None,
2312*760c253cSXin Li        # because GetCacheDirForRead is returning None at the moment.
2313*760c253cSXin Li        mock_runcmd.reset_mock()
2314*760c253cSXin Li        self.results_cache.cache_conditions = save_cc
2315*760c253cSXin Li        res = self.results_cache.ReadResult()
2316*760c253cSXin Li        self.assertIsNone(res)
2317*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 0)
2318*760c253cSXin Li
2319*760c253cSXin Li        # Test 3. Now set up cache dir to be returned by GetCacheDirForRead.
2320*760c253cSXin Li        # Since cache_dir is found, will call Result.CreateFromCacheHit, which
2321*760c253cSXin Li        # which will actually all our mock_create and should return fake_result.
2322*760c253cSXin Li        self.fakeCacheReturnResult = "fake/cache/dir"
2323*760c253cSXin Li        mock_create.return_value = fake_result
2324*760c253cSXin Li        res = self.results_cache.ReadResult()
2325*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 0)
2326*760c253cSXin Li        self.assertEqual(res, fake_result)
2327*760c253cSXin Li
2328*760c253cSXin Li        # Test 4. os.path.isdir(cache_dir) will now return false, so result
2329*760c253cSXin Li        # should be None again (no cache found).
2330*760c253cSXin Li        mock_isdir.return_value = False
2331*760c253cSXin Li        res = self.results_cache.ReadResult()
2332*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 0)
2333*760c253cSXin Li        self.assertIsNone(res)
2334*760c253cSXin Li
2335*760c253cSXin Li        # Test 5. os.path.isdir returns true, but mock_create now returns None
2336*760c253cSXin Li        # (the call to CreateFromCacheHit returns None), so overal result is
2337*760c253cSXin Li        # None.
2338*760c253cSXin Li        mock_isdir.return_value = True
2339*760c253cSXin Li        mock_create.return_value = None
2340*760c253cSXin Li        res = self.results_cache.ReadResult()
2341*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 0)
2342*760c253cSXin Li        self.assertIsNone(res)
2343*760c253cSXin Li
2344*760c253cSXin Li        # Test 6. Everything works 'as expected', result should be fake_result.
2345*760c253cSXin Li        mock_create.return_value = fake_result
2346*760c253cSXin Li        res = self.results_cache.ReadResult()
2347*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 0)
2348*760c253cSXin Li        self.assertEqual(res, fake_result)
2349*760c253cSXin Li
2350*760c253cSXin Li        # Test 7. The run failed; result should be None.
2351*760c253cSXin Li        mock_create.return_value = fake_result
2352*760c253cSXin Li        fake_result.retval = 1
2353*760c253cSXin Li        self.results_cache.cache_conditions.append(
2354*760c253cSXin Li            CacheConditions.RUN_SUCCEEDED
2355*760c253cSXin Li        )
2356*760c253cSXin Li        res = self.results_cache.ReadResult()
2357*760c253cSXin Li        self.assertEqual(mock_runcmd.call_count, 0)
2358*760c253cSXin Li        self.assertIsNone(res)
2359*760c253cSXin Li
2360*760c253cSXin Li
2361*760c253cSXin Liif __name__ == "__main__":
2362*760c253cSXin Li    unittest.main()
2363