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