1<?php 2 3/* 4 Phoronix Test Suite 5 URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ 6 Copyright (C) 2015 - 2021, Phoronix Media 7 Copyright (C) 2015 - 2021, Michael Larabel 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 21*/ 22 23class pts_stress_run_manager extends pts_test_run_manager 24{ 25 private $multi_test_stress_start_time; 26 private $stress_tests_executed; 27 private $sensor_data_archived; 28 private $sensor_data_archived_units; 29 private $sensor_data_archived_identifiers; 30 private $loop_until_time; 31 private $thread_collection_dir; 32 private $sensors_to_monitor; 33 private $stress_subsystems_active; 34 private $stress_child_thread = false; 35 private $stress_logger; 36 private $stress_log_event_call = false; 37 38 public $save_result_file = false; 39 public $save_result_identifier = false; 40 41 public static function stress_run($to_run, $batch_mode = false) 42 { 43 if($batch_mode == false) 44 { 45 $batch_mode = array( 46 'UploadResults' => false, 47 'SaveResults' => false, 48 'PromptForTestDescription' => false, 49 'RunAllTestCombinations' => false, 50 'PromptSaveName' => false, 51 'PromptForTestIdentifier' => false, 52 'OpenBrowser' => false 53 ); 54 } 55 $test_run_manager = new pts_stress_run_manager($batch_mode); 56 57 $tests_to_run_concurrently = 2; 58 59 echo PHP_EOL . pts_client::cli_just_bold('STRESS-RUN ENVIRONMENT VARIABLES:') . PHP_EOL; 60 61 if(($j = getenv('PTS_CONCURRENT_TEST_RUNS')) && is_numeric($j) && $j > 1) 62 { 63 $tests_to_run_concurrently = $j; 64 echo PHP_EOL . 'PTS_CONCURRENT_TEST_RUNS set; running ' . $tests_to_run_concurrently . ' tests concurrently.' . PHP_EOL . PHP_EOL; 65 } 66 else 67 { 68 echo PHP_EOL . pts_client::cli_just_bold('PTS_CONCURRENT_TEST_RUNS:') . ' Set the PTS_CONCURRENT_TEST_RUNS environment variable to specify how many tests should be run concurrently during the stress-run process. If not specified, defaults to 2.' . PHP_EOL . PHP_EOL; 69 } 70 71 // Run the actual tests 72 $total_loop_time = pts_client::read_env('TOTAL_LOOP_TIME'); 73 if($total_loop_time == 'infinite') 74 { 75 $total_loop_time = 'infinite'; 76 echo PHP_EOL . pts_client::cli_just_bold('TOTAL_LOOP_TIME') . ' set; running tests in an infinite loop until otherwise triggered' . PHP_EOL . PHP_EOL; 77 } 78 else if($total_loop_time && is_numeric($total_loop_time) && $total_loop_time > 1) 79 { 80 echo PHP_EOL . pts_client::cli_just_bold('TOTAL_LOOP_TIME') . ' set; running tests for ' . $total_loop_time . ' minutes' . PHP_EOL . PHP_EOL; 81 } 82 else 83 { 84 echo PHP_EOL . pts_client::cli_just_bold('TOTAL_LOOP_TIME:') . ' Set the TOTAL_LOOP_TIME environment variable if wishing to specify (in minutes) how long to run the stress-run process.' . PHP_EOL . PHP_EOL; 85 $total_loop_time = false; 86 } 87 88 if(($j = getenv('TEST_RESULTS_NAME'))) 89 { 90 $test_run_manager->save_result_file = pts_test_run_manager::clean_save_name($j); 91 $test_run_manager->result_file = new pts_result_file($test_run_manager->save_result_file); 92 $test_run_manager->result_file->set_title($j . ' Stress-Run Monitoring'); 93 echo PHP_EOL . pts_client::cli_just_bold('TEST_RESULTS_NAME') . ' set; saving the result sensor data as ' . $test_run_manager->save_result_file . '.' . PHP_EOL . PHP_EOL; 94 95 if(($j = getenv('TEST_RESULTS_IDENTIFIER'))) 96 { 97 $test_run_manager->save_result_identifier = $j; 98 echo PHP_EOL . pts_client::cli_just_bold('TEST_RESULTS_IDENTIFIER') . ' set; test identifier is ' . $test_run_manager->save_result_identifier . '.' . PHP_EOL . PHP_EOL; 99 } 100 else 101 { 102 $test_run_manager->save_result_identifier = date('Y-m-d H:i:s'); 103 echo PHP_EOL . pts_client::cli_just_bold('TEST_RESULTS_IDENTIFIER') . ' is not set; test identifier is ' . $test_run_manager->save_result_identifier . '.' . PHP_EOL . PHP_EOL; 104 } 105 106 $sys = new pts_result_file_system($test_run_manager->save_result_identifier, phodevi::system_hardware(true), phodevi::system_software(true), array(), pts_client::current_user(), null, date('Y-m-d H:i:s', pts_client::current_time()), PTS_VERSION, $test_run_manager->result_file); 107 $test_run_manager->result_file->add_system($sys); 108 } 109 else 110 { 111 echo PHP_EOL . pts_client::cli_just_bold('TEST_RESULTS_NAME') . ' is not set; set the TEST_RESULTS_NAME environment variable if wanting to save the sensor summary to a result file.' . PHP_EOL . PHP_EOL; 112 } 113 //pts_test_installer::standard_install($to_run); 114 /* 115 if(count($to_run) < $tests_to_run_concurrently) 116 { 117 echo PHP_EOL . 'More tests must be specified in order to run ' . $tests_to_run_concurrently . ' tests concurrently.'; 118 return false; 119 } 120 */ 121 122 if($test_run_manager->initial_checks($to_run, 'SHORT') == false) 123 { 124 return false; 125 } 126 127 // Load the tests to run 128 if($test_run_manager->load_tests_to_run($to_run) == false) 129 { 130 return false; 131 } 132 133 //$test_run_manager->pre_execution_process(); 134 $test_run_manager->multi_test_stress_run_execute($tests_to_run_concurrently, $total_loop_time); 135 } 136 public function multi_test_stress_run_execute($tests_to_run_concurrently = 3, $total_loop_time = false) 137 { 138 ini_set('memory_limit','8192M'); // XXX testing 139 140 $continue_test_flag = true; 141 pts_client::$display->test_run_process_start($this); 142 $this->allow_test_cache_share = false; 143 $this->disable_dynamic_run_count(); 144 $this->multi_test_stress_run = $tests_to_run_concurrently; 145 $possible_tests_to_run = $this->get_tests_to_run(); 146 147 // Cache test profiles to avoid unnecessary recreation for reading metadata from it 148 $test_profiles = array(); 149 // Cache pid to test identifier mapping to avoid extra reads of the PID file just to get the identifier 150 $pid_files_to_test_identifier = array(); 151 152 foreach($possible_tests_to_run as &$rr) 153 { 154 $test_profiles[$rr->test_profile->get_identifier()] = $rr->test_profile; 155 } 156 if(is_numeric($total_loop_time)) 157 { 158 $total_loop_time = $total_loop_time * 60; 159 } 160 $this->loop_until_time = is_numeric($total_loop_time) && $total_loop_time > 1 ? time() + $total_loop_time : false; 161 $this->stress_tests_executed = array(); 162 $this->multi_test_stress_start_time = time(); 163 $this->thread_collection_dir = pts_client::create_temporary_directory('stress-threads'); 164 $this->sensors_to_monitor = array(); 165 $this->sensor_data_archived = array(); 166 $this->sensor_data_archived_units = array(); 167 $this->sensor_data_archived_identifiers = array(); 168 $this->stress_logger = new pts_logger(null, 'phoronix-test-suite-stress-' . date('ymdHi') . '.log'); 169 $this->stress_logger->log('Log Initialized'); 170 putenv('FORCE_TIMES_TO_RUN=1'); 171 172 // Determine how frequently to print reports / status updates 173 $time_report_counter = time(); 174 if($total_loop_time == 'infinite') 175 { 176 $report_counter_frequency = 6 * 60; 177 } 178 else if($total_loop_time > (3 * 60 * 60)) 179 { 180 $report_counter_frequency = 30 * 60; 181 } 182 else if($total_loop_time > (60 * 60)) 183 { 184 $report_counter_frequency = 10 * 60; 185 } 186 else if($total_loop_time > (20 * 60)) 187 { 188 $report_counter_frequency = 5 * 60; 189 } 190 else if($total_loop_time > (10 * 60)) 191 { 192 $report_counter_frequency = 2 * 60; 193 } 194 else 195 { 196 $report_counter_frequency = 60; 197 } 198 199 // SIGTERM handling 200 if(function_exists('pcntl_signal')) 201 { 202 declare(ticks = 1); 203 pcntl_signal(SIGTERM, array($this, 'sig_handler')); 204 pcntl_signal(SIGHUP, array($this, 'sig_handler')); 205 pcntl_signal(SIGINT, array($this, 'sig_handler')); 206 } 207 else 208 { 209 $this->stress_print_and_log('PHP PCNTL support is needed if wishing to gracefully interrupt testing with signals.' . PHP_EOL); 210 } 211 212 // SENSOR SETUP WORK 213 $sensor_interval_frequency = is_numeric($total_loop_time) && $total_loop_time > 1 ? max($total_loop_time / 1000, 3) : 6; 214 $sensor_time_since_last_poll = time(); 215 foreach(phodevi::supported_sensors(array('cpu_temp', 'cpu_usage', 'gpu_usage', 'gpu_temp', 'hdd_read_speed', 'hdd_write_speed', 'memory_usage', 'swap_usage', 'sys_temp')) as $sensor) 216 { 217 $supported_devices = call_user_func(array($sensor[2], 'get_supported_devices')); 218 219 if($supported_devices === NULL) 220 { 221 $supported_devices = array(null); 222 } 223 224 foreach($supported_devices as $device) 225 { 226 $sensor_object = new $sensor[2](0, $device); 227 if(phodevi::read_sensor($sensor_object) != -1) 228 { 229 array_push($this->sensors_to_monitor, $sensor_object); 230 $this->sensor_data_archived[phodevi::sensor_object_name($sensor_object)] = array(); 231 $this->sensor_data_archived_units[phodevi::sensor_object_name($sensor_object)] = phodevi::read_sensor_object_unit($sensor_object); 232 $this->sensor_data_archived_identifiers[phodevi::sensor_object_name($sensor_object)] = phodevi::sensor_object_identifier($sensor_object); 233 } 234 } 235 } 236 237 $table = array(); 238 foreach(phodevi::system_hardware(false) as $component => $value) 239 { 240 $table[] = array($component . ': ', $value); 241 } 242 foreach(phodevi::system_software(false) as $component => $value) 243 { 244 $table[] = array($component . ': ', $value); 245 } 246 $this->stress_print_and_log('SYSTEM INFORMATION: ' . PHP_EOL . phodevi::system_centralized_view() . PHP_EOL . PHP_EOL); 247 if(!function_exists('pcntl_waitpid')) 248 { 249 $this->stress_print_and_log('PHP PCNTL support is to run stress tests.' . PHP_EOL); 250 return false; 251 252 } 253 pts_module_manager::module_process('__pre_run_process', $this); 254 255 // BEGIN THE LOOP 256 while(!empty($possible_tests_to_run)) 257 { 258 if($continue_test_flag == false) 259 break; 260 261 if(($time_report_counter + $report_counter_frequency) <= time() && count(pts_file_io::glob($this->thread_collection_dir . '*')) > 0) 262 { 263 // ISSUE STATUS REPORT 264 $this->stress_print_and_log($this->final_stress_report(false, $pid_files_to_test_identifier)); 265 $time_report_counter = time(); 266 } 267 268 $this->stress_subsystems_active = array(); 269 $test_identifiers_active = array(); 270 271 while(($waited_pid = pcntl_waitpid(-1, $status, WNOHANG)) > 0) 272 { 273 unset($pid_files_to_test_identifier[$waited_pid]); 274 pts_file_io::unlink($this->thread_collection_dir . $waited_pid); 275 } 276 277 foreach(pts_file_io::glob($this->thread_collection_dir . '*') as $pid_file) 278 { 279 $pid = basename($pid_file); 280 $waited_pid = pcntl_waitpid($pid, $status, WNOHANG); 281 282 if(!file_exists('/proc/' . $pid)) 283 { 284 unlink($pid_file); 285 unset($pid_files_to_test_identifier[$pid]); 286 continue; 287 } 288 289 if(!isset($test_profiles[$pid_files_to_test_identifier[$pid]])) 290 { 291 continue; 292 } 293 $test = $test_profiles[$pid_files_to_test_identifier[$pid]]; 294 295 // Count the number of tests per stress subsystems active 296 if(!isset($this->stress_subsystems_active[$test->get_test_hardware_type()])) 297 { 298 $this->stress_subsystems_active[$test->get_test_hardware_type()] = 1; 299 } 300 else 301 { 302 $this->stress_subsystems_active[$test->get_test_hardware_type()] += 1; 303 } 304 305 if(!in_array($test->get_identifier(), $test_identifiers_active)) 306 { 307 $test_identifiers_active[] = $test->get_identifier(); 308 } 309 310 } 311 312 if(!empty($possible_tests_to_run) && count(pts_file_io::glob($this->thread_collection_dir . '*')) < $this->multi_test_stress_run && (!$total_loop_time || $total_loop_time == 'infinite' || $this->loop_until_time > time())) 313 { 314 shuffle($possible_tests_to_run); 315 316 $test_to_run = false; 317 $test_run_index = -1; 318 319 if(getenv('DONT_BALANCE_TESTS_FOR_SUBSYSTEMS') == false) 320 { 321 // Try to pick a test for a hardware subsystem not yet being explicitly utilized 322 foreach($possible_tests_to_run as $i => $test) 323 { 324 $hw_subsystem_type = $test->test_profile->get_test_hardware_type(); 325 326 if(!isset($this->stress_subsystems_active[$hw_subsystem_type]) && !$this->skip_test_check($test)) 327 { 328 $test_run_index = $i; 329 $test_to_run = $test; 330 break; 331 } 332 } 333 } 334 335 if($test_run_index == -1 && getenv('DONT_TRY_TO_ENSURE_TESTS_ARE_UNIQUE') == false) 336 { 337 // Try to pick a test from a test profile not currently active 338 foreach($possible_tests_to_run as $i => $test) 339 { 340 if(!in_array($test->test_profile->get_identifier(), $test_identifiers_active) && !$this->skip_test_check($test)) 341 { 342 $test_run_index = $i; 343 $test_to_run = $test; 344 break; 345 } 346 } 347 } 348 349 if($test_run_index == -1) 350 { 351 // Last resort, just randomly pick a true "random" test 352 $test_run_index = array_rand(array_keys($possible_tests_to_run)); 353 $test_to_run = $possible_tests_to_run[$test_run_index]; 354 355 if($this->skip_test_check($test_to_run)) 356 { 357 continue; 358 } 359 } 360 361 $pid = pcntl_fork(); 362 if($pid == -1) 363 { 364 $this->stress_print_and_log('Forking Failure.'); 365 } 366 if($pid) 367 { 368 // parent 369 $test_identifier = $test_to_run->test_profile->get_identifier(); 370 file_put_contents($this->thread_collection_dir . $pid, $test_identifier); 371 $pid_files_to_test_identifier[$pid] = $test_identifier; 372 373 if(!isset($this->stress_tests_executed[$test_identifier])) 374 { 375 $this->stress_tests_executed[$test_identifier] = 1; 376 } 377 else 378 { 379 $this->stress_tests_executed[$test_identifier]++; 380 } 381 } 382 else 383 { 384 // child 385 $this->stress_child_thread = true; 386 //echo PHP_EOL . pts_client::cli_colored_text('Starting: ', 'green', true) . $test_to_run->test_profile->get_identifier() . ($test_to_run->get_arguments_description() != null ? ' [' . $test_to_run->get_arguments_description() . ']' : null) . PHP_EOL; 387 $continue_test_flag = $this->process_test_run_request($test_to_run); 388 //echo PHP_EOL . pts_client::cli_colored_text('Ended: ', 'red', true) . $test_to_run->test_profile->get_identifier() . ($test_to_run->get_arguments_description() != null ? ' [' . $test_to_run->get_arguments_description() . ']' : null) . PHP_EOL; 389 pts_file_io::unlink($this->thread_collection_dir . getmypid()); 390 unset($pid_files_to_test_identifier[getmypid()]); 391 //echo PHP_EOL; 392 exit(0); 393 } 394 if($total_loop_time == false) 395 { 396 unset($possible_tests_to_run[$test_run_index]); 397 } 398 else if($total_loop_time == 'infinite') 399 { 400 //$this->stress_print_and_log('Continuing to test indefinitely' . PHP_EOL); 401 } 402 else 403 { 404 if($this->loop_until_time > time()) 405 { 406 $time_left = ceil(($this->loop_until_time - time()) / 60); 407 // echo 'Continuing to test for ' . $time_left . ' more minutes' . PHP_EOL; 408 } 409 } 410 } 411 412 if(is_numeric($this->loop_until_time) && $this->loop_until_time < time()) 413 { 414 // Time to Quit 415 $this->stress_print_and_log('TEST TIME EXPIRED; NO NEW TESTS WILL EXECUTE; CURRENT TESTS WILL FINISH' . PHP_EOL); 416 // This halt-testing touch will let tests exit early (i.e. between multiple run steps) 417 file_put_contents(PTS_USER_PATH . 'halt-testing', 'stress-run is done... This text really is not important, just checking for file presence.'); 418 // Final report 419 $this->stress_print_and_log($this->final_stress_report(false, $pid_files_to_test_identifier)); 420 break; 421 } 422 423 if($sensor_time_since_last_poll + $sensor_interval_frequency < time()) 424 { 425 // Time to do a sensor reading 426 foreach($this->sensors_to_monitor as &$sensor_object) 427 { 428 $this->sensor_data_archived[phodevi::sensor_object_name($sensor_object)][] = phodevi::read_sensor($sensor_object); 429 } 430 $sensor_time_since_last_poll = time(); 431 } 432 } 433 434 pts_module_manager::module_process('__post_run_process', $this); 435 putenv('FORCE_TIMES_TO_RUN'); 436 pts_file_io::delete($this->thread_collection_dir, null, true); 437 438 foreach($this->get_tests_to_run() as $run_request) 439 { 440 // Remove cache shares 441 foreach(pts_file_io::glob($run_request->test_profile->get_install_dir() . 'cache-share-*.pt2so') as $cache_share_file) 442 { 443 unlink($cache_share_file); 444 } 445 } 446 447 // Wait for child processes to complete 448 //pcntl_waitpid(-1, $status); 449 450 // Restore default handlers 451 pcntl_signal(SIGTERM, SIG_DFL); 452 pcntl_signal(SIGINT, SIG_DFL); 453 pcntl_signal(SIGHUP, SIG_DFL); 454 455 return true; 456 } 457 public function is_interactive_mode() 458 { 459 return false; 460 } 461 protected function skip_test_check(&$test) 462 { 463 $hw_subsystem_type = $test->test_profile->get_test_hardware_type(); 464 $subsystem_limit_check = getenv('LIMIT_STRESS_' . strtoupper($hw_subsystem_type) . '_TESTS_COUNT'); 465 466 if(isset($this->stress_subsystems_active[$hw_subsystem_type]) && $subsystem_limit_check && $subsystem_limit_check <= $this->stress_subsystems_active[$hw_subsystem_type]) 467 { 468 // e.g. LIMIT_STRESS_GRAPHICS_TESTS_COUNT=2, don't want more than that number per subsystem concurrently 469 return true; 470 } 471 472 return false; 473 } 474 public function action_on_stress_log_set($call) 475 { 476 if(is_callable($call)) 477 { 478 $this->stress_log_event_call = $call; 479 } 480 } 481 protected function stress_print_and_log($msg) 482 { 483 if($this->stress_logger && $msg != null) 484 { 485 echo $msg; 486 $this->stress_logger->log($msg, false); 487 } 488 if($this->stress_log_event_call) 489 { 490 call_user_func($this->stress_log_event_call, $this->stress_logger->get_clean_log()); 491 } 492 } 493 public function get_stress_log() 494 { 495 return $this->stress_logger->get_clean_log(); 496 } 497 public function sig_handler($signo) 498 { 499 // Time to Quit 500 // This halt-testing touch will let tests exit early (i.e. between multiple run steps) 501 file_put_contents(PTS_USER_PATH . 'halt-testing', 'stress-run is done... This text really is not important, just checking for file presence.'); 502 503 if($this->stress_child_thread == false) 504 { 505 $this->stress_print_and_log('SIGNAL RECEIVED; QUITTING...' . PHP_EOL); 506 // Final report 507 $this->stress_print_and_log($this->final_stress_report()); 508 } 509 exit(); 510 } 511 protected function final_stress_report($is_final = true, $pid_files_to_test_identifier = null) 512 { 513 if(!$is_final) 514 { 515 $report_buffer = PHP_EOL . '###### STRESS RUN INTERIM REPORT ####' . PHP_EOL; 516 } 517 else 518 { 519 $report_buffer = PHP_EOL . '###### SUMMARY REPORT ####' . PHP_EOL; 520 } 521 522 $report_buffer .= strtoupper(date('F j H:i T')) . PHP_EOL; 523 $report_buffer .= pts_client::cli_just_bold('START TIME: ') . date('F j H:i T', $this->multi_test_stress_start_time) . PHP_EOL; 524 $report_buffer .= pts_client::cli_just_bold('ELAPSED TIME: ') . pts_strings::format_time(time() - $this->multi_test_stress_start_time) . PHP_EOL; 525 if($this->loop_until_time > time()) 526 { 527 $report_buffer .= pts_client::cli_just_bold('TIME REMAINING: ') . pts_strings::format_time($this->loop_until_time - time()) . PHP_EOL; 528 } 529 else 530 { 531 $report_buffer .= 'WAITING FOR CURRENT TEST RUN QUEUE TO FINISH.' . PHP_EOL; 532 } 533 $report_buffer .= pts_client::cli_just_bold('SYSTEM IP: ') . phodevi::read_property('network', 'ip') . PHP_EOL; 534 $report_buffer .= pts_client::cli_just_bold('HOSTNAME: ') . phodevi::read_property('system', 'hostname') . PHP_EOL; 535 $report_buffer .= pts_client::cli_just_bold('# OF CONCURRENT TESTS: ') . $this->multi_test_stress_run . PHP_EOL . PHP_EOL; 536 537 if(!$is_final) 538 { 539 $report_buffer .= 'TESTS CURRENTLY ACTIVE: ' . PHP_EOL; 540 541 $table = array(); 542 foreach(pts_file_io::glob($this->thread_collection_dir . '*') as $pid_file) 543 { 544 $pid_file_basename = basename($pid_file); 545 $test = isset($pid_files_to_test_identifier[$pid_file_basename]) ? $pid_files_to_test_identifier[$pid_file_basename] : pts_file_io::file_get_contents($pid_file); 546 $table[] = array($test, '[PID: ' . basename($pid_file) . ']'); 547 } 548 $report_buffer .= pts_user_io::display_text_table($table, ' - ', 2) . PHP_EOL; 549 } 550 551 $report_buffer .= PHP_EOL . pts_client::cli_just_bold('TESTS IN RUN QUEUE: ') . PHP_EOL . PHP_EOL; 552 $tiq = array(); 553 foreach($this->get_tests_to_run() as $i => $test) 554 { 555 $bar = pts_client::cli_colored_text(strtoupper($test->test_profile->get_title()) . ' [' . $test->test_profile->get_identifier() . ']', 'blue', true); 556 if(!isset($tiq[$bar])) 557 { 558 $tiq[$bar] = array(); 559 } 560 561 array_push($tiq[$bar], $test->get_arguments_description()); 562 } 563 foreach($tiq as $test => $args) 564 { 565 $report_buffer .= $test; 566 foreach($args as $arg) 567 { 568 if(!empty($arg)) 569 { 570 $report_buffer .= PHP_EOL . ' ' . $arg; 571 } 572 } 573 $report_buffer .= PHP_EOL; 574 } 575 576 if(!empty($this->stress_tests_executed)) 577 { 578 $table = array(array(pts_client::cli_just_bold('TESTS EXECUTED'), pts_client::cli_just_bold('TIMES CALLED'))); 579 ksort($this->stress_tests_executed); 580 581 foreach($this->stress_tests_executed as $test => $times) 582 { 583 $table[] = array(pts_client::cli_just_bold($test) . ': ', $times); 584 } 585 $report_buffer .= pts_user_io::display_text_table($table, ' ', 2) . PHP_EOL . PHP_EOL; 586 } 587 588 if($this->save_result_file) 589 { 590 $desc = $this->save_result_identifier . ': ' . $report_buffer; 591 } 592 593 $report_buffer .= PHP_EOL . pts_client::cli_just_bold('SYSTEM INFORMATION: ') . PHP_EOL; 594 $table = array(); 595 foreach(phodevi::system_hardware(false) as $component => $value) 596 { 597 $table[] = array(pts_client::cli_just_bold($component . ': '), $value); 598 } 599 foreach(phodevi::system_software(false) as $component => $value) 600 { 601 $table[] = array(pts_client::cli_just_bold($component . ': '), $value); 602 } 603 $report_buffer .= pts_user_io::display_text_table($table, ' ', 1) . PHP_EOL . PHP_EOL; 604 605 $report_buffer .= pts_client::cli_just_bold('SENSOR DATA: ') . PHP_EOL; 606 $table = array(array(pts_client::cli_just_bold('SENSOR'), pts_client::cli_just_bold('MIN'), pts_client::cli_just_bold('AVG'), pts_client::cli_just_bold('MAX'))); 607 foreach($this->sensor_data_archived as $sensor_name => &$sensor_data) 608 { 609 if(empty($sensor_data)) 610 continue; 611 612 $max_val = max($sensor_data); 613 614 if($max_val > 0) 615 { 616 $table[] = array(pts_client::cli_just_bold($sensor_name . ': '), 617 pts_math::set_precision(min($sensor_data), 2), 618 pts_math::set_precision(pts_math::arithmetic_mean($sensor_data), 2), 619 pts_math::set_precision($max_val, 2), 620 $this->sensor_data_archived_units[$sensor_name]); 621 622 if($this->save_result_file) 623 { 624 $test_profile = new pts_test_profile(); 625 $test_result = new pts_test_result($test_profile); 626 627 $test_result->test_profile->set_test_title($sensor_name . ' Monitor'); 628 $test_result->test_profile->set_identifier(null); 629 $test_result->test_profile->set_version(null); 630 $test_result->test_profile->set_result_proportion(null); 631 $test_result->test_profile->set_display_format('LINE_GRAPH'); 632 $test_result->test_profile->set_result_scale($this->sensor_data_archived_units[$sensor_name]); 633 $test_result->set_used_arguments_description('Phoronix Test Suite System Monitoring'); 634 $test_result->set_used_arguments($this->sensor_data_archived_identifiers[$sensor_name]); 635 $test_result->test_result_buffer = new pts_test_result_buffer(); 636 $test_result->test_result_buffer->add_test_result($this->save_result_identifier, implode(',', $sensor_data), implode(',', $sensor_data)); 637 $this->result_file->add_result_return_object($test_result); 638 } 639 } 640 } 641 $report_buffer .= pts_user_io::display_text_table($table, ' ', 2) . PHP_EOL; 642 $report_buffer .= '######' . PHP_EOL; 643 644 if($this->save_result_file) 645 { 646 $this->result_file->append_description($this->save_result_identifier . ': ' . $report_buffer); 647 pts_client::save_test_result($this->save_result_file . '/composite.xml', $this->result_file->get_xml(), true, $this->save_result_identifier); 648 $report_buffer .= pts_client::cli_just_bold('Result saved: ' . $this->save_result_file) . PHP_EOL; 649 } 650 651 return $report_buffer; 652 } 653} 654 655?> 656