public static function run($r)
 {
     $commands = array('detailed_system_info' => null, 'list_available_tests' => null, 'list_available_suites' => null, 'info' => array('xonotic'), 'clone_openbenchmarking_result' => array('1107247-LI-MESACOMMI48'), 'result_file_to_text' => array('1107247-LI-MESACOMMI48'), 'diagnostics' => null, 'dump_possible_options' => null);
     $individual_times = array();
     phodevi::clear_cache();
     $start = microtime(true);
     foreach ($commands as $command => $args) {
         echo PHP_EOL . '### ' . $command . ' ###' . PHP_EOL;
         $individual_times[$command] = array();
         for ($i = 0; $i < 3; $i++) {
             $c_start = microtime(true);
             pts_client::execute_command($command, $args);
             $c_finish = microtime(true);
             array_push($individual_times[$command], $c_finish - $c_start);
         }
     }
     $finish = microtime(true);
     echo PHP_EOL . PHP_EOL . '### OVERALL DATA ###' . PHP_EOL . PHP_EOL;
     echo 'PHP:  ' . PTS_PHP_VERSION . PHP_EOL;
     $longest_c = max(array_map('strlen', array_keys($individual_times)));
     foreach ($individual_times as $component => $times) {
         echo strtoupper($component) . ': ' . str_repeat(' ', $longest_c - strlen($component)) . pts_math::set_precision(round(array_sum($times) / count($times), 3), 3) . ' seconds' . PHP_EOL;
     }
     echo PHP_EOL . 'ELAPSED TIME: ' . str_repeat(' ', $longest_c - strlen('ELAPSED TIME')) . round($finish - $start, 3) . ' seconds';
     echo PHP_EOL . 'PEAK MEMORY USAGE: ' . str_repeat(' ', $longest_c - strlen('PEAK MEMORY USAGE')) . round(memory_get_peak_usage(true) / 1048576, 3) . ' MB';
     echo PHP_EOL . 'PEAK MEMORY USAGE (emalloc): ' . str_repeat(' ', $longest_c - strlen('PEAK MEMORY USAGE (emalloc)')) . round(memory_get_peak_usage() / 1048576, 3) . ' MB';
     echo PHP_EOL;
 }
 public static function run($r)
 {
     define('PHOROMATIC_PROCESS', true);
     $commands = array('detailed_system_info' => null, 'list_available_tests' => null, 'list_available_suites' => null, 'info' => array('pts/all'), 'clone_openbenchmarking_result' => array('1107247-LI-MESACOMMI48', '1509040-HA-GCCINTELS17', '1508201-HA-GTX95073337', '1508233-HA-INTELSKYL16'), 'refresh_graphs' => array('1107247-LI-MESACOMMI48'), 'result_file_to_text' => array('1107247-LI-MESACOMMI48'), 'merge_results' => array('1107247-LI-MESACOMMI48', '1509040-HA-GCCINTELS17', '1508201-HA-GTX95073337', '1508233-HA-INTELSKYL16'), 'diagnostics' => null, 'dump_possible_options' => null, 'debug_render_test' => null);
     $individual_times = array();
     phodevi::clear_cache();
     $start = microtime(true);
     foreach ($commands as $command => $args) {
         echo PHP_EOL . '### ' . $command . ' ###' . PHP_EOL;
         $individual_times[$command] = array();
         for ($i = 0; $i < 3; $i++) {
             $c_start = microtime(true);
             pts_client::execute_command($command, $args);
             $c_finish = microtime(true);
             $individual_times[$command][] = $c_finish - $c_start;
         }
     }
     $finish = microtime(true);
     echo PHP_EOL . PHP_EOL . '### OVERALL DATA ###' . PHP_EOL . PHP_EOL;
     echo 'PHP:  ' . PTS_PHP_VERSION . PHP_EOL;
     $longest_c = max(array_map('strlen', array_keys($individual_times)));
     foreach ($individual_times as $component => $times) {
         echo strtoupper($component) . ': ' . str_repeat(' ', $longest_c - strlen($component)) . pts_math::set_precision(round(array_sum($times) / count($times), 3), 3) . ' seconds' . PHP_EOL;
     }
     echo PHP_EOL . 'TOTAL ELAPSED TIME: ' . str_repeat(' ', $longest_c - strlen('ELAPSED TIME')) . round($finish - $start, 3) . ' seconds';
     echo PHP_EOL . 'PEAK MEMORY USAGE: ' . str_repeat(' ', $longest_c - strlen('PEAK MEMORY USAGE')) . round(memory_get_peak_usage(true) / 1048576, 3) . ' MB';
     echo PHP_EOL . 'PEAK MEMORY USAGE EMALLOC: ' . str_repeat(' ', $longest_c - strlen('PEAK MEMORY USAGE (emalloc)')) . round(memory_get_peak_usage() / 1048576, 3) . ' MB';
     echo PHP_EOL;
 }
 private function mem_usage_bsd($TYPE = 'TOTAL', $READ = 'USED')
 {
     $vmstats = explode("\n", shell_exec('vm_stat 2>&1'));
     // buffers_and_cache
     foreach ($vmstats as $vmstat_line) {
         $line_parts = pts_strings::colon_explode($vmstat_line);
         if (self::$page_size == -1) {
             strtok($vmstat_line, ':');
             $tok = strtok(' ');
             while (self::$page_size == -1) {
                 if (is_numeric($tok)) {
                     self::$page_size = $tok;
                 } else {
                     $tok = strtok(' ');
                 }
             }
             continue;
         }
         //$line_parts[1] = pts_strings::trim_spaces($line_parts[1]);
         $line_type = strtok($vmstat_line, ':');
         $line_value = strtok(' .');
         if ($TYPE == 'MEMORY') {
             if ($line_type == 'Pages active' && $READ == 'USED') {
                 $mem_usage = $line_value / (1048576 / self::$page_size);
                 break;
             }
             if ($line_type == 'Pages free' && $READ == 'FREE') {
                 $mem_usage = $line_value / (1048576 / self::$page_size);
                 break;
             }
         }
     }
     return pts_math::set_precision($mem_usage);
 }
 public static function read_sensor()
 {
     // Determine current percentage for processor usage
     if (phodevi::is_linux() || phodevi::is_bsd()) {
         $start_load = self::cpu_load_array(-1);
         sleep(1);
         $end_load = self::cpu_load_array(-1);
         for ($i = 0; $i < count($end_load); $i++) {
             $end_load[$i] -= $start_load[$i];
         }
         $percent = ($sum = array_sum($end_load)) == 0 ? 0 : 100 - $end_load[count($end_load) - 1] * 100 / $sum;
     } else {
         if (phodevi::is_solaris()) {
             // TODO: Add support for monitoring load on a per-core basis (through mpstat maybe?)
             $info = explode(' ', pts_strings::trim_spaces(pts_arrays::last_element(explode("\n", trim(shell_exec('sar -u 1 1 2>&1'))))));
             $percent = $info[1] + $info[2];
         } else {
             if (phodevi::is_macosx()) {
                 // CPU usage for user
                 $top = shell_exec('top -n 1 -l 1 2>&1');
                 $top = substr($top, strpos($top, 'CPU usage: ') + 11);
                 $percent = substr($top, 0, strpos($top, '%'));
             } else {
                 $percent = null;
             }
         }
     }
     if (!is_numeric($percent) || $percent < 0 || $percent > 100) {
         $percent = -1;
     }
     return pts_math::set_precision($percent, 2);
 }
 protected function render_graph_bars()
 {
     $bar_count = count($this->graph_data);
     $separator_width = ($a = 8 - floor($bar_count / 2) * 2) > 0 ? $a : 0;
     $bar_width = floor(($this->i['identifier_width'] - $separator_width - $bar_count * $separator_width) / $bar_count);
     for ($i_o = 0; $i_o < $bar_count; $i_o++) {
         $paint_color = $this->get_paint_color(isset($this->graph_data_title[$i_o]) ? $this->graph_data_title[$i_o] : null);
         foreach (array_keys($this->graph_data[$i_o]) as $i) {
             $value = pts_math::set_precision($this->graph_data[$i_o][$i], 2);
             $graph_size = round($value / $this->i['graph_max_value'] * ($this->i['graph_top_end'] - $this->i['top_start']));
             $value_plot_top = max($this->i['graph_top_end'] + 1 - $graph_size, 1);
             $px_bound_left = $this->i['left_start'] + $this->i['identifier_width'] * $i + $bar_width * $i_o + $separator_width * ($i_o + 1);
             $px_bound_right = $px_bound_left + $bar_width;
             $title_tooltip = $this->graph_identifiers[$i] . ': ' . $value;
             $run_std_deviation = isset($this->graph_data_raw[$i_o][$i]) ? pts_math::standard_deviation(pts_strings::colon_explode($this->graph_data_raw[$i_o][$i])) : 0;
             if ($run_std_deviation > 0) {
                 $title_tooltip .= ' || ' . pts_math::set_precision($run_std_deviation, 1) . ' STD';
             }
             $this->svg_dom->add_element('rect', array('x' => $px_bound_left + 1, 'y' => $value_plot_top, 'width' => $bar_width, 'height' => $this->i['graph_top_end'] - $value_plot_top, 'fill' => in_array($this->graph_identifiers[$i], $this->value_highlights) ? self::$c['color']['alert'] : $paint_color, 'stroke' => self::$c['color']['body_light'], 'stroke-width' => 1, 'xlink:title' => $title_tooltip));
             if ($px_bound_right - $px_bound_left < 15) {
                 // The bars are too skinny to be able to plot anything on them
                 continue;
             }
             $x = $px_bound_left + ($px_bound_right - $px_bound_left) / 2;
             if ($graph_size > 18) {
                 $this->svg_dom->add_text_element($value, array('x' => $x, 'y' => $value_plot_top + 2, 'font-size' => floor(self::$c['size']['bars'] * 0.9), 'fill' => self::$c['color']['body_text'], 'text-anchor' => 'middle', 'dominant-baseline' => 'text-before-edge'));
             } else {
                 // Make things more compact
                 $this->svg_dom->add_text_element($value, array('x' => $x, 'y' => $value_plot_top + 2, 'font-size' => floor(self::$c['size']['bars'] * 0.6), 'fill' => self::$c['color']['body_text'], 'text-anchor' => 'middle', 'dominant-baseline' => 'text-before-edge'));
             }
         }
     }
     // write a new line along the bottom since the draw_rectangle_with_border above had written on top of it
     $this->svg_dom->draw_svg_line($this->i['left_start'], $this->i['graph_top_end'], $this->i['graph_left_end'], $this->i['graph_top_end'], self::$c['color']['notches'], 1);
 }
 private function cpu_temp_linux()
 {
     $temp_c = -1;
     // Try hwmon interface
     $raw_temp = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/temp2_input', 'POSITIVE_NUMERIC', array('name' => 'coretemp'));
     if ($raw_temp == -1) {
         $raw_temp = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/device/temp1_input', 'POSITIVE_NUMERIC', array('name' => 'k10temp'));
     }
     if ($raw_temp == -1) {
         // Try ACPI thermal
         // Assuming the system thermal sensor comes 2nd to the ACPI CPU temperature
         // It appears that way on a ThinkPad T60, but TODO find a better way to validate
         $raw_temp = phodevi_linux_parser::read_sysfs_node('/sys/class/thermal/thermal_zone*/temp', 'POSITIVE_NUMERIC', null, 2);
     }
     if ($raw_temp != -1) {
         if ($raw_temp > 1000) {
             $raw_temp = $raw_temp / 1000;
         }
         $temp_c = pts_math::set_precision($raw_temp, 2);
     }
     if ($temp_c == -1) {
         // Try LM_Sensors
         $sensors = phodevi_linux_parser::read_sensors(array('CPU Temp', 'Core 0', 'Core0 Temp', 'Core1 Temp'));
         if ($sensors != false && is_numeric($sensors) && $sensors > 0) {
             $temp_c = $sensors;
         }
     }
     if (pts_client::executable_in_path('ipmitool')) {
         $ipmi = phodevi_linux_parser::read_ipmitool_sensor('Temp 0');
         if ($ipmi > 0 && is_numeric($ipmi)) {
             $temp_c = $ipmi;
         }
     }
     return $temp_c;
 }
 public function read_sensor()
 {
     $net_speed = -1;
     if (phodevi::is_bsd() || phodevi::is_macosx()) {
         $net_speed = $this->network_usage_bsd();
     }
     return pts_math::set_precision($net_speed, 2);
 }
 public function read_sensor()
 {
     $temp = -1;
     if (phodevi::is_linux()) {
         $temp = $this->hdd_temp_linux();
     }
     return pts_math::set_precision($temp, 2);
 }
 public function read_sensor()
 {
     $write_speed = -1;
     if (phodevi::is_linux()) {
         $write_speed = $this->hdd_write_speed_linux();
     }
     return pts_math::set_precision($write_speed, 2);
 }
 protected function bytes_to_download_size($bytes)
 {
     $mb = pts_math::set_precision($bytes / 1048576, 2);
     if ($mb > 99) {
         $mb = ceil($mb);
     }
     return $mb;
 }
 public static function read_sensor()
 {
     // Read the processor temperature
     $temp_c = -1;
     if (phodevi::is_bsd()) {
         $cpu_temp = phodevi_bsd_parser::read_sysctl(array('hw.sensors.acpi_tz0.temp0', 'dev.cpu.0.temperature', 'hw.sensors.cpu0.temp0'));
         if ($cpu_temp != false) {
             if (($end = strpos($cpu_temp, 'degC')) || ($end = strpos($cpu_temp, 'C')) > 0) {
                 $cpu_temp = substr($cpu_temp, 0, $end);
             }
             if (is_numeric($cpu_temp)) {
                 $temp_c = $cpu_temp;
             }
         } else {
             $acpi = phodevi_bsd_parser::read_sysctl('hw.acpi.thermal.tz0.temperature');
             if (($end = strpos($acpi, 'C')) > 0) {
                 $acpi = substr($acpi, 0, $end);
             }
             if (is_numeric($acpi)) {
                 $temp_c = $acpi;
             }
         }
     } else {
         if (phodevi::is_linux()) {
             // Try hwmon interface
             $raw_temp = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/device/temp1_input', 'POSITIVE_NUMERIC', array('name' => 'coretemp'));
             if ($raw_temp == -1) {
                 $raw_temp = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/device/temp1_input', 'POSITIVE_NUMERIC', array('name' => 'k10temp'));
             }
             if ($raw_temp == -1) {
                 // Try ACPI thermal
                 // Assuming the system thermal sensor comes 2nd to the ACPI CPU temperature
                 // It appears that way on a ThinkPad T60, but TODO find a better way to validate
                 $raw_temp = phodevi_linux_parser::read_sysfs_node('/sys/class/thermal/thermal_zone*/temp', 'POSITIVE_NUMERIC', null, 2);
             }
             if ($raw_temp != -1) {
                 if ($raw_temp > 1000) {
                     $raw_temp = $raw_temp / 1000;
                 }
                 $temp_c = pts_math::set_precision($raw_temp, 2);
             }
             if ($temp_c == -1) {
                 // Try LM_Sensors
                 $sensors = phodevi_linux_parser::read_sensors(array('CPU Temp', 'Core 0', 'Core0 Temp', 'Core1 Temp'));
                 if ($sensors != false && is_numeric($sensors) && $sensors > 0) {
                     $temp_c = $sensors;
                 }
             }
             if (pts_client::executable_in_path('ipmitool')) {
                 $ipmi = phodevi_linux_parser::read_ipmitool_sensor('Temp 0');
                 if ($ipmi > 0 && is_numeric($ipmi)) {
                     $temp_c = $ipmi;
                 }
             }
         }
     }
     return $temp_c;
 }
 public static function percent_standard_deviation($values)
 {
     if (count($values) == 0) {
         // No values
         return 0;
     }
     $standard_deviation = pts_math::standard_deviation($values);
     $average_value = array_sum($values) / count($values);
     return $average_value != 0 ? $standard_deviation / $average_value * 100 : 0;
 }
 public function increase_run_count_check(&$test_results, $scheduled_times_to_run, $latest_test_run_time)
 {
     // First make sure this test doesn't take too long to run where we don't want dynamic handling
     if (floor($latest_test_run_time / 60) > $this->dynamic_run_count_on_length_or_less) {
         return false;
     }
     // Determine if results are statistically significant, otherwise up the run count
     $std_dev = pts_math::percent_standard_deviation($test_results->test_result_buffer->get_values());
     if ($std_dev >= $this->dynamic_run_count_std_deviation_threshold) {
         static $last_run_count = 128;
         // just a number that should always cause the first check below to be true
         static $run_std_devs;
         $times_already_ran = $test_results->test_result_buffer->get_count();
         if ($times_already_ran <= $last_run_count) {
             // We're now onto a new test so clear out the array
             $run_std_devs = array();
         }
         $last_run_count = $times_already_ran;
         $run_std_devs[$last_run_count] = $std_dev;
         // If we haven't reached scheduled times to run x 2, increase count straight away
         if ($times_already_ran < $scheduled_times_to_run * 2) {
             return true;
         } else {
             if ($times_already_ran < $scheduled_times_to_run * 3) {
                 // More aggressive determination whether to still keep increasing the run count
                 $first_and_now_diff = pts_arrays::first_element($run_std_devs) - pts_arrays::last_element($run_std_devs);
                 // Increasing the run count at least looks to be helping...
                 if ($first_and_now_diff > pts_arrays::first_element($run_std_devs) / 2) {
                     // If we are at least making progress in the right direction, increase the run count some more
                     return true;
                 }
                 // TODO: could add more checks and take better advantage of the array of data to better determine if it's still worth increasing
             }
         }
     }
     // Check to see if there is an external/custom script to export the results to in determining whether results are valid
     if (($ex_file = $this->dynamic_run_count_export_script) != null && is_executable($ex_file) || is_executable($ex_file = PTS_USER_PATH . $this->dynamic_run_count_export_script)) {
         $exit_status = trim(shell_exec($ex_file . ' ' . $test_results->test_result_buffer->get_values_as_string() . ' > /dev/null 2>&1; echo $?'));
         switch ($exit_status) {
             case 1:
                 // Run the test again
                 return true;
             case 2:
                 // Results are bad, abandon testing and do not record results
                 return -1;
             case 0:
             default:
                 // Return was 0 or something else, results are valid, or was some other exit status
                 break;
         }
     }
     // No reason to increase the run count with none of the previous checks requesting otherwise
     return false;
 }
 public function get_change_formatted()
 {
     $direction = '-';
     if ($this->test_proportion == 'HIB' && $this->get_regressed_value() > $this->get_base_value()) {
         $direction = '+';
     } else {
         if ($this->test_proportion == 'LIB' && $this->get_regressed_value() < $this->get_base_value()) {
             $direction = '+';
         }
     }
     return $direction . pts_math::set_precision($this->get_change() * 100, 2);
 }
 public static function read_sensor()
 {
     // Reads the system's temperature
     $temp_c = -1;
     if (phodevi::is_linux()) {
         $raw_temp = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/device/temp3_input', 'POSITIVE_NUMERIC', array('name' => '!coretemp,!radeon,!nouveau'));
         if ($raw_temp == -1) {
             $raw_temp = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/device/temp2_input', 'POSITIVE_NUMERIC', array('name' => '!coretemp,!radeon,!nouveau'));
         }
         if ($raw_temp == -1) {
             $raw_temp = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/device/temp1_input', 'POSITIVE_NUMERIC', array('name' => '!coretemp,!radeon,!nouveau'));
         }
         if ($raw_temp == -1) {
             $raw_temp = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/temp1_input', 'POSITIVE_NUMERIC');
         }
         if ($raw_temp != -1) {
             if ($raw_temp > 1000) {
                 $raw_temp = $raw_temp / 1000;
             }
             $temp_c = pts_math::set_precision($raw_temp, 2);
         }
         if ($temp_c == -1) {
             $acpi = phodevi_linux_parser::read_acpi(array('/thermal_zone/THM1/temperature', '/thermal_zone/TZ00/temperature', '/thermal_zone/TZ01/temperature'), 'temperature');
             if (($end = strpos($acpi, ' ')) > 0) {
                 $temp_c = substr($acpi, 0, $end);
             }
         }
         if ($temp_c == -1) {
             $sensors = phodevi_linux_parser::read_sensors(array('Sys Temp', 'Board Temp'));
             if ($sensors != false && is_numeric($sensors)) {
                 $temp_c = $sensors;
             }
         }
         if ($temp_c == -1 && is_file('/sys/class/thermal/thermal_zone0/temp')) {
             $temp_c = pts_file_io::file_get_contents('/sys/class/thermal/thermal_zone0/temp');
             if ($temp_c > 1000) {
                 $temp_c = pts_math::set_precision($temp_c / 1000, 1);
             }
         }
     } else {
         if (phodevi::is_bsd()) {
             $acpi = phodevi_bsd_parser::read_sysctl(array('hw.sensors.acpi_tz1.temp0', 'hw.acpi.thermal.tz1.temperature'));
             if (($end = strpos($acpi, ' degC')) > 0 || ($end = strpos($acpi, 'C')) > 0) {
                 $acpi = substr($acpi, 0, $end);
                 if (is_numeric($acpi)) {
                     $temp_c = $acpi;
                 }
             }
         }
     }
     return $temp_c;
 }
 private function swap_usage_linux()
 {
     $proc_meminfo = explode("\n", file_get_contents('/proc/meminfo'));
     $mem = array();
     foreach ($proc_meminfo as $mem_line) {
         $line_split = preg_split('/\\s+/', $mem_line);
         if (count($line_split) == 3) {
             $mem[$line_split[0]] = intval($line_split[1]);
         }
     }
     $used_mem = $mem['SwapTotal:'] - $mem['SwapFree:'];
     return pts_math::set_precision($used_mem / 1024, 0);
 }
 private function cpu_power_linux()
 {
     $cpu_watts = -1;
     // Try hwmon interface for AMD 15h (Bulldozer FX CPUs) where this support was introduced for AMD CPUs and exposed by the fam15h_power hwmon driver
     // The fam15h_power driver doesn't expose the power consumption on a per-core/per-package basis but only an average
     $hwmon_watts = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/device/power1_input', 'POSITIVE_NUMERIC', array('name' => 'fam15h_power'));
     if ($hwmon_watts != -1) {
         if ($hwmon_watts > 1000000) {
             // convert to Watts
             $hwmon_watts = $hwmon_watts / 1000000;
         }
         $cpu_watts = pts_math::set_precision($hwmon_watts, 2);
     }
     return $cpu_watts;
 }
 public function read_sensor()
 {
     $start_sys_jiffies = self::cpu_jiffies_count();
     $start_cgroup_jiffies = self::cgroup_cpu_jiffies_count();
     usleep(500000);
     $end_sys_jiffies = self::cpu_jiffies_count();
     $end_cgroup_jiffies = self::cgroup_cpu_jiffies_count();
     $diff_sys_jiffies = $end_sys_jiffies - $start_sys_jiffies;
     $diff_cgroup_jiffies = $end_cgroup_jiffies - $start_cgroup_jiffies;
     $percent = $diff_sys_jiffies == 0 ? 0 : $diff_cgroup_jiffies / $diff_sys_jiffies * 100;
     if (!is_numeric($percent) || $percent < 0 || $percent > 100) {
         $percent = -1;
     }
     return pts_math::set_precision($percent, 2);
 }
 public static function read_sensor()
 {
     $iowait = -1;
     if (phodevi::is_linux() && is_file('/proc/stat')) {
         $start_stat = pts_file_io::file_get_contents('/proc/stat');
         sleep(1);
         $end_stat = pts_file_io::file_get_contents('/proc/stat');
         $start_stat = explode(' ', substr($start_stat, 0, strpos($start_stat, "\n")));
         $end_stat = explode(' ', substr($end_stat, 0, strpos($end_stat, "\n")));
         for ($i = 2, $diff_cpu_total = 0; $i < 9; $i++) {
             $diff_cpu_total += $end_stat[$i] - $start_stat[$i];
         }
         $diff_iowait = $end_stat[6] - $start_stat[6];
         $iowait = pts_math::set_precision(1000 * $diff_iowait / $diff_cpu_total / 10, 2);
     }
     return $iowait;
 }
 public function render_graph_finish()
 {
     $this->render_graph_identifiers();
     $this->render_graph_heading(false);
     $pie_slices = count($this->graph_identifiers);
     $radius = min($this->i['graph_height'] - $this->i['top_start'] - $this->i['top_end_bottom'], $this->i['graph_width'] - $this->i['left_start'] - $this->i['left_end_right']) / 2;
     $center_x = $this->i['graph_width'] / 2;
     $center_y = $this->i['top_start'] + ($this->i['graph_height'] - $this->i['top_start'] - $this->i['top_end_bottom']) / 2;
     $offset_percent = 0;
     for ($i = 0; $i < $pie_slices; $i++) {
         $percent = pts_math::set_precision($this->graph_data[0][$i] / $this->i['pie_sum'], 3);
         $this->svg_dom->draw_svg_arc($center_x, $center_y, $radius, $offset_percent, $percent, array('fill' => $this->get_paint_color($i), 'stroke' => self::$c['color']['border'], 'stroke-width' => 2, 'xlink:title' => $this->graph_identifiers[$i] . ': ' . $this->graph_data[0][$i]));
         $offset_percent += $percent;
     }
     if (!empty(self::$c['text']['watermark'])) {
         $this->svg_dom->add_text_element(self::$c['text']['watermark'], array('x' => $this->i['graph_width'] / 2, 'y' => $this->i['graph_height'] - 15, 'font-size' => 10, 'fill' => self::$c['color']['text'], 'text-anchor' => 'middle', 'dominant-baseline' => 'text-before-edge'));
     }
 }
 public static function read_sensor()
 {
     // Determine the current processor frequency
     $cpu_core = 0;
     // TODO: for now just monitoring the first core
     $info = 0;
     if (phodevi::is_linux()) {
         // First, the ideal way, with modern CPUs using CnQ or EIST and cpuinfo reporting the current
         if (is_file('/sys/devices/system/cpu/cpu' . $cpu_core . '/cpufreq/scaling_cur_freq')) {
             $info = pts_file_io::file_get_contents('/sys/devices/system/cpu/cpu' . $cpu_core . '/cpufreq/scaling_cur_freq');
             $info = intval($info) / 1000;
         } else {
             if (is_file('/proc/cpuinfo')) {
                 $cpu_speeds = phodevi_linux_parser::read_cpuinfo('cpu MHz');
                 if (isset($cpu_speeds[0])) {
                     $cpu_core = isset($cpu_speeds[$cpu_core]) ? $cpu_core : 0;
                     $info = intval($cpu_speeds[$cpu_core]);
                 }
             }
         }
     } else {
         if (phodevi::is_solaris()) {
             $info = shell_exec('psrinfo -v | grep MHz');
             $info = substr($info, strrpos($info, 'at') + 3);
             $info = trim(substr($info, 0, strpos($info, 'MHz')));
         } else {
             if (phodevi::is_bsd()) {
                 $info = phodevi_bsd_parser::read_sysctl('dev.cpu.0.freq');
             } else {
                 if (phodevi::is_macosx()) {
                     $info = phodevi_osx_parser::read_osx_system_profiler('SPHardwareDataType', 'ProcessorSpeed');
                     if (($cut_point = strpos($info, ' ')) > 0) {
                         $info = substr($info, 0, $cut_point);
                         $info = str_replace(',', '.', $info);
                     }
                     if ($info < 100) {
                         $info *= 1000;
                     }
                 }
             }
         }
     }
     return pts_math::set_precision($info, 2);
 }
 public function read_sensor()
 {
     // Determine current percentage for core usage
     // Default core to read is the first one (number 0)
     if (phodevi::is_linux() || phodevi::is_bsd()) {
         $percent = $this->cpu_usage_linux_bsd();
     } else {
         if (phodevi::is_solaris()) {
             $percent = $this->cpu_usage_solaris();
         } else {
             if (phodevi::is_macosx()) {
                 $percent = $this->cpu_usage_macosx();
             }
         }
     }
     if (!isset($percent) || !is_numeric($percent) || $percent < 0 || $percent > 100) {
         $percent = -1;
     }
     return pts_math::set_precision($percent, 2);
 }
 private function sys_temp_linux()
 {
     $temp_c = -1;
     $raw_temp = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/device/temp3_input', 'POSITIVE_NUMERIC', array('name' => '!coretemp,!radeon,!nouveau'));
     if ($raw_temp == -1) {
         $raw_temp = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/device/temp2_input', 'POSITIVE_NUMERIC', array('name' => '!coretemp,!radeon,!nouveau'));
     }
     if ($raw_temp == -1) {
         $raw_temp = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/device/temp1_input', 'POSITIVE_NUMERIC', array('name' => '!coretemp,!radeon,!nouveau'));
     }
     if ($raw_temp == -1) {
         $raw_temp = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/temp1_input', 'POSITIVE_NUMERIC');
     }
     if ($raw_temp != -1) {
         if ($raw_temp > 1000) {
             $raw_temp = $raw_temp / 1000;
         }
         $temp_c = pts_math::set_precision($raw_temp, 2);
     }
     if ($temp_c == -1) {
         $acpi = phodevi_linux_parser::read_acpi(array('/thermal_zone/THM1/temperature', '/thermal_zone/TZ00/temperature', '/thermal_zone/TZ01/temperature'), 'temperature');
         if (($end = strpos($acpi, ' ')) > 0) {
             $temp_c = substr($acpi, 0, $end);
         }
     }
     if ($temp_c == -1) {
         $sensors = phodevi_linux_parser::read_sensors(array('Sys Temp', 'Board Temp'));
         if ($sensors != false && is_numeric($sensors)) {
             $temp_c = $sensors;
         }
     }
     if ($temp_c == -1 && is_file('/sys/class/thermal/thermal_zone0/temp')) {
         $temp_c = pts_file_io::file_get_contents('/sys/class/thermal/thermal_zone0/temp');
         if ($temp_c > 1000) {
             $temp_c = pts_math::set_precision($temp_c / 1000, 1);
         }
     }
     return $temp_c;
 }
 public static function generate_overview_object(&$overview_table, $overview_type)
 {
     switch ($overview_type) {
         case 'GEOMETRIC_MEAN':
             $title = 'Geometric Mean';
             $math_call = array('pts_math', 'geometric_mean');
             break;
         case 'HARMONIC_MEAN':
             $title = 'Harmonic Mean';
             $math_call = array('pts_math', 'harmonic_mean');
             break;
         case 'AGGREGATE_SUM':
             $title = 'Aggregate Sum';
             $math_call = 'array_sum';
             break;
         default:
             return false;
     }
     $result_buffer = new pts_test_result_buffer();
     if ($overview_table instanceof pts_result_file) {
         list($days_keys1, $days_keys, $shred) = pts_ResultFileTable::result_file_to_result_table($overview_table);
         foreach ($shred as $system_key => &$system) {
             $to_show = array();
             foreach ($system as &$days) {
                 $days = $days->get_value();
             }
             array_push($to_show, pts_math::set_precision(call_user_func($math_call, $system), 2));
             $result_buffer->add_test_result($system_key, implode(',', $to_show), null);
         }
     } else {
         $days_keys = null;
         foreach ($overview_table as $system_key => &$system) {
             if ($days_keys == null) {
                 // TODO: Rather messy and inappropriate way of getting the days keys
                 $days_keys = array_keys($system);
                 break;
             }
         }
         foreach ($overview_table as $system_key => &$system) {
             $to_show = array();
             foreach ($system as &$days) {
                 array_push($to_show, call_user_func($math_call, $days));
             }
             $result_buffer->add_test_result($system_key, implode(',', $to_show), null);
         }
     }
     $test_profile = new pts_test_profile(null, null, false);
     $test_profile->set_test_title($title);
     $test_profile->set_result_scale($title);
     $test_profile->set_display_format('BAR_GRAPH');
     $test_result = new pts_test_result($test_profile);
     $test_result->set_used_arguments_description('Analytical Overview');
     $test_result->set_test_result_buffer($result_buffer);
     return $test_result;
 }
 protected function renderGraphLines()
 {
     $prev_value = 0;
     foreach ($this->test_result->test_result_buffer->buffer_items as &$buffer_item) {
         $paint_color = $this->get_paint_color($buffer_item->get_result_identifier());
         $result_array = $buffer_item->get_result_value();
         $raw_array = $buffer_item->get_result_raw();
         $point_counter = count($result_array);
         $regression_plots = array();
         $poly_points = array();
         $g = $this->svg_dom->make_g(array('stroke' => $paint_color, 'stroke-width' => 1, 'fill' => $paint_color));
         for ($i = 0; $i < $point_counter; $i++) {
             $value = isset($result_array[$i]) ? $result_array[$i] : -1;
             if ($value < 0) {
                 // Draw whatever is needed of the line so far, since there is no result here
                 $this->draw_graph_line_process($poly_points, $paint_color, $regression_plots, $point_counter, $g);
                 continue;
             }
             $identifier = $buffer_item->get_result_identifier();
             $std_error = isset($raw_array[$i]) ? pts_math::standard_error(pts_strings::colon_explode($raw_array[$i])) : 0;
             $data_string = $identifier . ': ' . $value;
             $value_plot_top = $this->i['graph_top_end'] + 1 - ($this->i['graph_max_value'] == 0 ? 0 : round($value / $this->i['graph_max_value'] * ($this->i['graph_top_end'] - $this->i['top_start'])));
             $px_from_left = round($this->i['left_start'] + $this->i['identifier_width'] * ($i + (count($this->graph_identifiers) > 1 ? 1 : 0)));
             if ($px_from_left > $this->i['graph_left_end']) {
                 break;
             }
             if ($value_plot_top >= $this->i['graph_top_end']) {
                 $value_plot_top = $this->i['graph_top_end'] - 1;
             }
             array_push($poly_points, array($px_from_left, $value_plot_top, $data_string, $std_error));
             if (isset($this->d['regression_marker_threshold']) && $this->d['regression_marker_threshold'] > 0 && $i > 0 && abs(1 - $value / $prev_value) > $this->d['regression_marker_threshold']) {
                 $regression_plots[$i - 1] = $prev_identifier . ': ' . $prev_value;
                 $regression_plots[$i] = $identifier . ': ' . $value;
             }
             $prev_identifier = $identifier;
             $prev_value = $value;
         }
         $this->draw_graph_line_process($poly_points, $paint_color, $regression_plots, $point_counter, $g);
     }
 }
 public function remove_noisy_results($threshold = 0.6)
 {
     if ($this->test_profile->get_display_format() != 'BAR_GRAPH') {
         return false;
     }
     $is_multi_way = pts_render::multi_way_identifier_check($this->test_result_buffer->get_identifiers());
     $keys = array_keys($this->test_result_buffer->buffer_items);
     if ($is_multi_way) {
         $key_sets = array();
         foreach ($keys as $k) {
             $identifier_r = pts_strings::trim_explode(': ', $this->test_result_buffer->buffer_items[$k]->get_result_identifier());
             if (!isset($key_sets[$identifier_r[0]])) {
                 $key_sets[$identifier_r[0]] = array();
             }
             $key_sets[$identifier_r[0]][] = $k;
         }
     } else {
         $key_sets = array($keys);
     }
     foreach ($key_sets as $keys) {
         $jiggy_results = 0;
         foreach ($keys as $k) {
             $raw = $this->test_result_buffer->buffer_items[$k]->get_result_raw();
             if (!empty($raw)) {
                 $raw = pts_math::standard_error(pts_strings::colon_explode($raw));
                 if ($raw > 10) {
                     $jiggy_results++;
                 }
             }
         }
         if ($jiggy_results / count($keys) > $threshold) {
             foreach ($keys as $k) {
                 unset($this->test_result_buffer->buffer_items[$k]);
             }
         }
     }
     return true;
 }
 private static function process_perf_per_watt_collection(&$test_run_manager)
 {
     if (count(self::$perf_per_watt_collection) > 2) {
         // Performance per watt overall
         $avg = array_sum(self::$perf_per_watt_collection) / count(self::$perf_per_watt_collection);
         $test_profile = new pts_test_profile();
         $test_result = new pts_test_result($test_profile);
         $test_result->test_profile->set_test_title('Meta Performance Per Watt');
         $test_result->test_profile->set_identifier(null);
         $test_result->test_profile->set_version(null);
         $test_result->test_profile->set_result_proportion(null);
         $test_result->test_profile->set_display_format('BAR_GRAPH');
         $test_result->test_profile->set_result_scale('Performance Per Watt');
         $test_result->test_profile->set_result_proportion('HIB');
         $test_result->set_used_arguments_description('Performance Per Watt');
         $test_result->set_used_arguments('Per-Per-Watt');
         $test_result->test_result_buffer = new pts_test_result_buffer();
         $test_result->test_result_buffer->add_test_result(self::$result_identifier, pts_math::set_precision($avg));
         $test_run_manager->result_file->add_result($test_result);
     }
 }
 public function normalize_buffer_values($normalize_against = false)
 {
     if ($this->test_profile->get_display_format() != 'BAR_GRAPH') {
         return false;
     }
     $is_multi_way = pts_render::multi_way_identifier_check($this->test_result_buffer->get_identifiers());
     $keys = array_keys($this->test_result_buffer->buffer_items);
     if ($is_multi_way) {
         $key_sets = array();
         foreach ($keys as $k) {
             $identifier_r = pts_strings::trim_explode(': ', $this->test_result_buffer->buffer_items[$k]->get_result_identifier());
             if (!isset($key_sets[$identifier_r[0]])) {
                 $key_sets[$identifier_r[0]] = array();
             }
             array_push($key_sets[$identifier_r[0]], $k);
         }
     } else {
         $key_sets = array($keys);
     }
     foreach ($key_sets as $keys) {
         if ($this->test_profile->get_result_proportion() == 'LIB') {
             // Invert values for LIB
             foreach ($keys as $k) {
                 $this->test_result_buffer->buffer_items[$k]->reset_result_value(1 / $this->test_result_buffer->buffer_items[$k]->get_result_value());
             }
         }
         $divide_value = -1;
         if ($normalize_against != false) {
             foreach ($keys as $k) {
                 if ($is_multi_way && strpos($this->test_result_buffer->buffer_items[$k]->get_result_identifier(), ': ' . $normalize_against) !== false) {
                     // This allows it to just normalize against part of the string
                     $divide_value = $this->test_result_buffer->buffer_items[$k]->get_result_value();
                     break;
                 } else {
                     if ($this->test_result_buffer->buffer_items[$k]->get_result_identifier() == $normalize_against) {
                         $divide_value = $this->test_result_buffer->buffer_items[$k]->get_result_value();
                         break;
                     }
                 }
             }
         }
         if ($divide_value == -1) {
             foreach ($keys as $k) {
                 if ($this->test_result_buffer->buffer_items[$k]->get_result_value() < $divide_value || $divide_value == -1) {
                     $divide_value = $this->test_result_buffer->buffer_items[$k]->get_result_value();
                 }
             }
         }
         if ($divide_value != 0) {
             foreach ($keys as $k) {
                 $normalized = pts_math::set_precision($this->test_result_buffer->buffer_items[$k]->get_result_value() / $divide_value, max(3, $this->result_precision));
                 $this->test_result_buffer->buffer_items[$k]->reset_result_value($normalized);
                 $this->test_result_buffer->buffer_items[$k]->reset_raw_value(0);
             }
         }
     }
     $this->test_profile->set_result_proportion('HIB');
     $this->test_profile->set_result_scale('Relative Performance');
     return true;
 }
 protected static function process_user_config_external_hook_process($process, $cmd_value, $description_string = null, &$passed_obj = null)
 {
     if (!empty($cmd_value) && (is_executable($cmd_value) || ($cmd_value = pts_client::executable_in_path($cmd_value)))) {
         $descriptor_spec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
         $env_vars = array('PTS_EXTERNAL_TEST_HOOK' => $process);
         if ($passed_obj instanceof pts_test_result) {
             $env_vars['PTS_EXTERNAL_TEST_IDENTIFIER'] = $passed_obj->test_profile->get_identifier();
             $env_vars['PTS_EXTERNAL_TEST_RUN_POSITION'] = $passed_obj->test_result_buffer->get_count() + 1;
             $env_vars['PTS_EXTERNAL_TEST_RUN_COUNT'] = $passed_obj->test_profile->get_times_to_run();
             $env_vars['PTS_EXTERNAL_TEST_ARGS'] = $passed_obj->get_arguments();
             $env_vars['PTS_EXTERNAL_TEST_DESCRIPTION'] = $passed_obj->get_arguments_description();
             $env_vars['PTS_EXTERNAL_TEST_RESULT_SET'] = $passed_obj->test_result_buffer->get_values_as_string();
             $env_vars['PTS_EXTERNAL_TEST_RESULT'] = $passed_obj->get_result() != 0 ? $passed_obj->get_result() : pts_arrays::last_element($passed_obj->test_result_buffer->get_values());
             $env_vars['PTS_EXTERNAL_TEST_HASH'] = bin2hex($passed_obj->get_comparison_hash());
             $env_vars['PTS_EXTERNAL_TEST_STD_DEV_PERCENT'] = pts_math::percent_standard_deviation($passed_obj->test_result_buffer->get_values());
             if (is_file($passed_obj->test_profile->get_install_dir() . 'cache-share-' . PTS_INIT_TIME . '.pt2so')) {
                 // There's a cache share present
                 $env_vars['PTS_EXTERNAL_TEST_CACHE_SHARE'] = 1;
             }
         } else {
             if ($passed_obj instanceof pts_test_run_manager) {
                 $env_vars['PTS_EXTERNAL_TESTS_IN_QUEUE'] = implode(':', $passed_obj->get_tests_to_run_identifiers());
                 $env_vars['PTS_EXTERNAL_TEST_FILE_NAME'] = $passed_obj->get_file_name();
                 $env_vars['PTS_EXTERNAL_TEST_IDENTIFIER'] = $passed_obj->get_results_identifier();
             }
         }
         $description_string != null && pts_client::$display->test_run_instance_error($description_string);
         $proc = proc_open($cmd_value, $descriptor_spec, $pipes, null, $env_vars);
         $std_output = stream_get_contents($pipes[1]);
         $return_value = proc_close($proc);
         // If you want PTS to exit or something when your script returns !0, you could add an 'exit;' or whatever you want below
         // The contents of $std_output is anything that may have been written by your script, if you want it to be interpreted by anything in this module
         if ($return_value != 0) {
             return false;
         }
     }
     return true;
 }
 protected function render_graph_bars()
 {
     $bar_count = count($this->results);
     $separator_height = ($a = 6 - floor($bar_count / 2) * 2) > 0 ? $a : 0;
     $bar_height = floor(($this->i['identifier_height'] - ($this->is_multi_way_comparison ? 4 : 0) - $separator_height - $bar_count * $separator_height) / $bar_count);
     $this->i['graph_max_value'] = $this->i['graph_max_value'] != 0 ? $this->i['graph_max_value'] : 1;
     $work_area_width = $this->i['graph_left_end'] - $this->i['left_start'];
     $group_offsets = array();
     $id_offsets = array();
     $g_bars = $this->svg_dom->make_g(array('stroke' => self::$c['color']['body_light'], 'stroke-width' => 1));
     foreach ($this->results as $identifier => &$group) {
         $paint_color = $this->get_paint_color($identifier);
         foreach ($group as &$buffer_item) {
             $values = $buffer_item->get_result_value();
             $values = explode(',', $values);
             if (empty($values) || count($values) < 2) {
                 $values = $buffer_item->get_result_raw();
                 $values = explode(':', $values);
             }
             if (empty($values) || count($values) < 2) {
                 continue;
             }
             if (isset($values[10])) {
                 // Ignore any zeros at the start
                 if ($values[0] == 0 && $values[5] != 0) {
                     $j = 0;
                     while ($values[$j] == 0) {
                         unset($values[$j]);
                         $j++;
                     }
                 }
                 // Ignore any zeros at the end
                 if ($values[count($values) - 1] == 0 && $values[count($values) - 5] != 0) {
                     $j = count($values) - 1;
                     while ($values[$j] == 0) {
                         unset($values[$j]);
                         $j--;
                     }
                 }
             }
             $i_o = $this->calc_offset($group_offsets, $identifier);
             $i = $this->calc_offset($id_offsets, $buffer_item->get_result_identifier());
             $px_bound_top = $this->i['top_start'] + ($this->is_multi_way_comparison ? 5 : 0) + $this->i['identifier_height'] * $i + $bar_height * $i_o + $separator_height * ($i_o + 1);
             $px_bound_bottom = $px_bound_top + $bar_height;
             $middle_of_bar = $px_bound_top + $bar_height / 2;
             $avg_value = round(array_sum($values) / count($values), 2);
             $whisker_bottom = pts_math::find_percentile($values, 0.02);
             $whisker_top = pts_math::find_percentile($values, 0.98);
             $median = pts_math::find_percentile($values, 0.5);
             $unique_values = array_unique($values);
             $min_value = round(min($unique_values), 2);
             $max_value = round(max($unique_values), 2);
             $stat_value = 'Min: ' . $min_value . ' / Avg: ' . $avg_value . ' / Max: ' . $max_value;
             $title_tooltip = $buffer_item->get_result_identifier() . ': ' . $stat_value;
             $value_end_left = $this->i['left_start'] + max(1, round($whisker_bottom / $this->i['graph_max_value'] * $work_area_width));
             $value_end_right = $this->i['left_start'] + round($whisker_top / $this->i['graph_max_value'] * $work_area_width);
             $box_color = in_array($buffer_item->get_result_identifier(), $this->value_highlights) ? self::$c['color']['highlight'] : $paint_color;
             $this->svg_dom->draw_svg_line($value_end_left, $middle_of_bar, $value_end_right, $middle_of_bar, $box_color, 2, array('xlink:title' => $title_tooltip));
             $this->svg_dom->draw_svg_line($value_end_left, $px_bound_top, $value_end_left, $px_bound_bottom, self::$c['color']['notches'], 2, array('xlink:title' => $title_tooltip));
             $this->svg_dom->draw_svg_line($value_end_right, $px_bound_top, $value_end_right, $px_bound_bottom, self::$c['color']['notches'], 2, array('xlink:title' => $title_tooltip));
             $box_left = $this->i['left_start'] + round(pts_math::find_percentile($values, 0.25) / $this->i['graph_max_value'] * $work_area_width);
             $box_middle = $this->i['left_start'] + round($median / $this->i['graph_max_value'] * $work_area_width);
             $box_right = $this->i['left_start'] + round(pts_math::find_percentile($values, 0.75) / $this->i['graph_max_value'] * $work_area_width);
             $this->svg_dom->add_element('rect', array('x' => $box_left, 'y' => $px_bound_top, 'width' => $box_right - $box_left, 'height' => $bar_height, 'fill' => $box_color, 'xlink:title' => $title_tooltip), $g_bars);
             $this->svg_dom->draw_svg_line($box_middle, $px_bound_top, $box_middle, $px_bound_bottom, self::$c['color']['notches'], 2, array('xlink:title' => $title_tooltip));
             $this->svg_dom->add_text_element($stat_value, array('x' => $this->i['left_start'] - 5, 'y' => ceil($px_bound_top + $bar_height * 0.8 + 6), 'font-size' => $this->i['identifier_size'] - 2, 'fill' => self::$c['color']['text'], 'text-anchor' => 'end'));
             foreach ($unique_values as &$val) {
                 if (($val < $whisker_bottom || $val > $whisker_top) && $val > 0.1) {
                     $this->svg_dom->draw_svg_circle($this->i['left_start'] + round($val / $this->i['graph_max_value'] * $work_area_width), $middle_of_bar, 1, self::$c['color']['notches']);
                 }
             }
         }
     }
     // write a new line along the bottom since the draw_rectangle_with_border above had written on top of it
     $this->svg_dom->draw_svg_line($this->i['left_start'], $this->i['graph_top_end'], $this->i['graph_left_end'], $this->i['graph_top_end'], self::$c['color']['notches'], 1);
 }