phoronix-test-suite/pts-core/external-test-dependencies/xml/xsl/pts-generic-exdep-viewer.xsl0000644000175000017500000000336511564533734032577 0ustar michaelmichael Phoronix Test Suite - External Dependencies
Phoronix Test Suite - External Dependencies
External Dependency Name
Possible Package Names
File / Directory Check

()
Copyright © 2008 - 2009 by Phoronix Media.
phoronix-test-suite/pts-core/external-test-dependencies/xml/xsl/pts-exdep-viewer.xsl0000644000175000017500000000350111564533734031155 0ustar michaelmichael Phoronix Test Suite - <xsl:value-of select="PhoronixTestSuite/ExternalDependencies/Information/Name" /> Dependencies
Dependencies
Generic Name
Package Name(s)
File Check
Copyright © 2008 - 2009 by Phoronix Media.
phoronix-test-suite/pts-core/objects/phodevi/sensors/gpu_freq.php0000644000175000017500000001207012201104340025441 0ustar michaelmichael. */ class gpu_freq implements phodevi_sensor { public static function get_type() { return 'gpu'; } public static function get_sensor() { return 'freq'; } public static function get_unit() { return 'Megahertz'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test > 0; } public static function read_sensor() { // Graphics processor real/current frequency $show_memory = false; $core_freq = 0; $mem_freq = 0; if(phodevi::is_nvidia_graphics()) // NVIDIA GPU { $nv_freq = phodevi_parser::read_nvidia_extension('GPUCurrentClockFreqs'); $nv_freq = pts_strings::comma_explode($nv_freq); $core_freq = isset($nv_freq[0]) ? $nv_freq[0] : 0; $mem_freq = isset($nv_freq[1]) ? $nv_freq[1] : 0; } else if(phodevi::is_ati_graphics() && phodevi::is_linux()) // ATI GPU { $od_clocks = phodevi_linux_parser::read_ati_overdrive('CurrentClocks'); if(is_array($od_clocks) && count($od_clocks) >= 2) // ATI OverDrive { $core_freq = array_shift($od_clocks); $mem_freq = array_pop($od_clocks); } } else if(phodevi::is_linux()) { if(isset(phodevi::$vfs->radeon_pm_info)) { // radeon_pm_info should be present with Linux 2.6.34+ foreach(pts_strings::trim_explode("\n", phodevi::$vfs->radeon_pm_info) as $pm_line) { $pm_line = pts_strings::colon_explode($pm_line); if(isset($pm_line[1])) { list($descriptor, $value) = $pm_line; } else { continue; } switch($descriptor) { case 'current engine clock': $core_freq = pts_arrays::first_element(explode(' ', $value)) / 1000; break; case 'current memory clock': $mem_freq = pts_arrays::first_element(explode(' ', $value)) / 1000; break; } } if($core_freq == null && ($x = strpos(phodevi::$vfs->radeon_pm_info, 'sclk: '))) { $x = substr(phodevi::$vfs->radeon_pm_info, ($x + strlen('sclk: '))); $x = substr($x, 0, strpos($x, ' ')); if(is_numeric($x)) { if($x > 1000) { $x = $x / 100; } $core_freq = $x; } } if($mem_freq == null && ($x = strpos(phodevi::$vfs->radeon_pm_info, 'mclk: '))) { $x = substr(phodevi::$vfs->radeon_pm_info, ($x + strlen('mclk: '))); $x = substr($x, 0, strpos($x, ' ')); if(is_numeric($x)) { if($x > 1000) { $x = $x / 100; } $mem_freq = $x; } } } else if(is_file('/sys/class/drm/card0/gt_cur_freq_mhz')) { $gt_cur_freq_mhz = pts_file_io::file_get_contents('/sys/class/drm/card0/gt_cur_freq_mhz'); if($gt_cur_freq_mhz > 2) { $core_freq = $gt_cur_freq_mhz; } } else if(is_file('/sys/class/drm/card0/device/performance_level')) { $performance_level = pts_file_io::file_get_contents('/sys/class/drm/card0/device/performance_level'); $performance_level = explode(' ', $performance_level); $core_string = array_search('core', $performance_level); if($core_string !== false && isset($performance_level[($core_string + 1)])) { $core_string = str_ireplace('MHz', null, $performance_level[($core_string + 1)]); if(is_numeric($core_string) && $core_string > $core_freq) { $core_freq = $core_string; } } $mem_string = array_search('memory', $performance_level); if($mem_string !== false && isset($performance_level[($mem_string + 1)])) { $mem_string = str_ireplace('MHz', null, $performance_level[($mem_string + 1)]); if(is_numeric($mem_string) && $mem_string > $mem_freq) { $mem_freq = $mem_string; } } } else if(isset(phodevi::$vfs->i915_cur_delayinfo)) { $i915_cur_delayinfo = phodevi::$vfs->i915_cur_delayinfo; $cagf = strpos($i915_cur_delayinfo, 'CAGF: '); if($cagf !== false) { $cagf_mhz = substr($i915_cur_delayinfo, $cagf + 6); $cagf_mhz = substr($cagf_mhz, 0, strpos($cagf_mhz, 'MHz')); if(is_numeric($cagf_mhz)) { $core_freq = $cagf_mhz; } } } } if(!is_numeric($core_freq)) { $core_freq = 0; } if(!is_numeric($mem_freq)) { $mem_freq = 0; } if($core_freq == 0 && $mem_freq == 0) { $show_memory = false; $core_freq = -1; } return $show_memory ? array($core_freq, $mem_freq) : $core_freq; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/cpu_temp.php0000644000175000017500000000635412032445730025472 0ustar michaelmichael. */ class cpu_temp implements phodevi_sensor { public static function get_type() { return 'cpu'; } public static function get_sensor() { return 'temp'; } public static function get_unit() { return 'Celsius'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } 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; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/gpu_voltage.php0000644000175000017500000000372612201104746026167 0ustar michaelmichael. */ class gpu_voltage implements phodevi_sensor { public static function get_type() { return 'gpu'; } public static function get_sensor() { return 'voltage'; } public static function get_unit() { return 'mV'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } public static function read_sensor() { $sensor = -1; // TODO XXX: Nouveau driver exposes GPU voltage on at least some cards via performance_level if(isset(phodevi::$vfs->radeon_pm_info)) { // For Radeon power management it should be exposed on a line like: // voltage: 1140 mV if(($x = strpos(phodevi::$vfs->radeon_pm_info, 'voltage: ')) !== false) { $radeon_pm_info = substr($radeon_pm_info, ($x + 9)); if(($x = stripos($radeon_pm_info, ' mV')) !== false) { $sensor = substr($radeon_pm_info, 0, $x); } } if($sensor == null && ($x = strpos(phodevi::$vfs->radeon_pm_info, 'vddc: '))) { $x = ltrim(substr(phodevi::$vfs->radeon_pm_info, ($x + strlen('vddc: ')))); $x = substr($x, 0, strpos($x, ' ')); if(is_numeric($x)) { $sensor = $x; } } } return $sensor; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/sys_power.php0000644000175000017500000001407612157204620025707 0ustar michaelmichael. */ class sys_power implements phodevi_sensor { private static $battery_sys = false; private static $battery_cur = false; private static $wattsup_meter = false; private static $ipmitool = false; public static function get_type() { return 'sys'; } public static function get_sensor() { return 'power'; } public static function get_unit() { if(self::$battery_sys) { $unit = 'Milliwatts'; } else if(self::$battery_cur) { $unit = 'microAmps'; } else if(self::$wattsup_meter || self::$ipmitool) { $unit = 'Watts'; } return $unit; } public static function support_check() { $test = self::sys_battery_power(); if(is_numeric($test) && $test != -1) { self::$battery_sys = true; return true; } $test = self::sys_power_current(); if(is_numeric($test) && $test != -1) { self::$battery_cur = true; return true; } if(pts_client::executable_in_path('wattsup')) { $wattsup = self::watts_up_power_meter(); if($wattsup > 0.5 && is_numeric($wattsup)) { self::$wattsup_meter = true; return true; } } if(pts_client::executable_in_path('ipmitool')) { $ipmi_read = phodevi_linux_parser::read_ipmitool_sensor('Node Power'); if($ipmi_read > 0 && is_numeric($ipmi_read)) { self::$ipmitool = true; return true; } } } public static function read_sensor() { if(self::$battery_sys) { return self::sys_battery_power(); } else if(self::$battery_cur) { return self::sys_power_current(); } else if(self::$wattsup_meter) { return self::watts_up_power_meter(); } else if(self::$ipmitool) { return phodevi_linux_parser::read_ipmitool_sensor('Node Power'); } } private static function watts_up_power_meter() { $output = trim(shell_exec('wattsup -c 1 ttyUSB0 watts 2>&1')); $output = explode(PHP_EOL, $output); do { $value = array_pop($output); } while(!is_numeric($value) && count($output) > 0); return is_numeric($value) ? $value : -1; } private static function sys_power_current() { // Returns power consumption rate in uA $current = -1; if(phodevi::is_linux()) { $raw_current = phodevi_linux_parser::read_sysfs_node('/sys/devices/w1_bus_master1/*/getcurrent', 'NO_CHECK'); if($raw_current != -1) { if(substr($raw_current, 0, 1) == '-') { $current = substr($raw_current, 1); } } } else if(phodevi::is_macosx()) { $current = abs(phodevi_osx_parser::read_osx_system_profiler('SPPowerDataType', 'Amperage')); // in mA } return $current; } private static function sys_battery_power() { // Returns power consumption rate in mW $rate = -1; if(phodevi::is_linux()) { $power_now = phodevi_linux_parser::read_sysfs_node('/sys/class/power_supply/*/power_now', 'POSITIVE_NUMERIC', array('status' => 'Discharging')); if($power_now != -1) { // sysfs power_now seems to be displayed in microWatts $rate = pts_math::set_precision($power_now / 1000, 2); } if($rate == -1) { $battery = array('/battery/BAT0/state', '/battery/BAT1/state'); $state = phodevi_linux_parser::read_acpi($battery, 'charging state'); $power = phodevi_linux_parser::read_acpi($battery, 'present rate'); $voltage = phodevi_linux_parser::read_acpi($battery, 'present voltage'); if($state == 'discharging') { $power_unit = substr($power, strrpos($power, ' ') + 1); $power = substr($power, 0, strpos($power, ' ')); if($power_unit == 'mA') { $voltage_unit = substr($voltage, strrpos($voltage, ' ') + 1); $voltage = substr($voltage, 0, strpos($voltage, ' ')); if($voltage_unit == 'mV') { $rate = round(($power * $voltage) / 1000); } } else if($power_unit == 'mW') { $rate = $power; } } } if($rate == -1 && is_file('/sys/class/power_supply/BAT0/voltage_now') && is_file('/sys/class/power_supply/BAT0/current_now')) { $voltage_now = pts_file_io::file_get_contents('/sys/class/power_supply/BAT0/voltage_now') / 1000; $current_now = pts_file_io::file_get_contents('/sys/class/power_supply/BAT0/current_now') / 1000; $power_now = $voltage_now * $current_now / 1000; if($power_now > 1) { $rate = $power_now; } } } else if(phodevi::is_macosx()) { $amperage = abs(phodevi_osx_parser::read_osx_system_profiler('SPPowerDataType', 'Amperage')); // in mA $voltage = phodevi_osx_parser::read_osx_system_profiler('SPPowerDataType', 'Voltage'); // in mV if($amperage > 0 && $voltage > 0) { $rate = round(($amperage * $voltage) / 1000); } else if(pts_client::executable_in_path('ioreg')) { $ioreg = trim(shell_exec("ioreg -l | grep LegacyBatteryInfo | cut -d '{' -f 2 | tr -d \} | tr ',' '=' | awk -F'=' '{print ($2*$10/10^22)}' 2>&1")); if(is_numeric($ioreg) && $ioreg > 0) { $rate = $ioreg; } } } else if(phodevi::is_solaris()) { $battery = phodevi_solaris_parser::read_hal_property('/org/freedesktop/Hal/devices/pseudo/acpi_drv_0_battery0_0', 'battery.reporting.rate'); if(is_numeric($battery)) { $rate = $battery; } } else if(phodevi::is_bsd()) { $battery = phodevi_bsd_parser::read_acpiconf('Present rate'); if($battery && substr($battery, -2) == 'mW') { $rate = substr($battery, 0, strpos($battery, ' ')); } } return $rate; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/sys_temp.php0000644000175000017500000000635311666714567025543 0ustar michaelmichael. */ class sys_temp implements phodevi_sensor { public static function get_type() { return 'sys'; } public static function get_sensor() { return 'temp'; } public static function get_unit() { return 'Celsius'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } 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; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/gpu_usage.php0000644000175000017500000001201711565242546025640 0ustar michaelmichael. */ class gpu_usage implements phodevi_sensor { static $probe_ati_overdrive = false; static $probe_radeon_fences = false; static $probe_intel_commands = false; static $probe_nvidia_smi = false; public static function get_type() { return 'gpu'; } public static function get_sensor() { return 'usage'; } public static function get_unit() { if(self::$probe_ati_overdrive || self::$probe_nvidia_smi) { $unit = 'Percent'; } else if(self::$probe_radeon_fences) { $unit = 'Fences/s'; } else if(self::$probe_intel_commands) { $unit = 'Commands/s'; } return $unit; } public static function support_check() { if(phodevi::is_ati_graphics() && phodevi::is_linux()) { $gpu_usage = self::ati_overdrive_core_usage(); if(is_numeric($gpu_usage)) { self::$probe_ati_overdrive = true; return true; } } else if(phodevi::is_mesa_graphics()) { if(is_readable('/sys/kernel/debug/dri/0/radeon_fence_info')) { $fence_speed = self::radeon_fence_speed(); if(is_numeric($fence_speed) && $fence_speed >= 0) { self::$probe_radeon_fences = true; return true; } } else if(is_readable('/sys/kernel/debug/dri/0/i915_gem_seqno')) { $commands = self::intel_command_speed(); if(is_numeric($commands) && $commands > 0) { self::$probe_intel_commands = true; return true; } } } else if(phodevi::is_nvidia_graphics()) { if(pts_client::executable_in_path('nvidia-smi')) { $usage = self::nvidia_core_usage(); if(is_numeric($usage) && $usage >= 0 && $usage <= 100) { self::$probe_nvidia_smi = true; return true; } } } return false; } public static function read_sensor() { if(self::$probe_ati_overdrive) { return self::ati_overdrive_core_usage(); } else if(self::$probe_nvidia_smi) { return self::nvidia_core_usage(); } else if(self::$probe_radeon_fences) { return self::radeon_fence_speed(); } else if(self::$probe_intel_commands) { return self::intel_command_speed(); } } public static function ati_overdrive_core_usage() { return phodevi_linux_parser::read_ati_overdrive('GPUload'); } public static function nvidia_core_usage() { $nvidia_smi = shell_exec('nvidia-smi -a'); $util = substr($nvidia_smi, strpos($nvidia_smi, 'Utilization')); $util = substr($util, strpos($util, 'GPU')); $util = substr($util, strpos($util, ':') + 1); $util = trim(substr($util, 0, strpos($util, '%'))); return $util; } public static function radeon_fence_speed() { // Determine GPU usage $fence_speed = -1; /* Last signaled fence 0x00AF9AF1 Last emited fence ffff8800ac0e2080 with 0x00AF9AF1 */ $fence_info = file_get_contents('/sys/kernel/debug/dri/0/radeon_fence_info'); $start_signaled_fence = substr($fence_info, strpos('Last signaled fence', $fence_info)); $start_signaled_fence = substr($start_signaled_fence, 0, strpos($start_signaled_fence, "\n")); $start_signaled_fence = substr($start_signaled_fence, strrpos($start_signaled_fence, ' ')); sleep(1); $fence_info = file_get_contents('/sys/kernel/debug/dri/0/radeon_fence_info'); $end_signaled_fence = substr($fence_info, strpos('Last signaled fence', $fence_info)); $end_signaled_fence = substr($end_signaled_fence, 0, strpos($end_signaled_fence, "\n")); $end_signaled_fence = substr($end_signaled_fence, strrpos($end_signaled_fence, ' ')); $fence_speed = hexdec($end_signaled_fence) - hexdec($start_signaled_fence); return $fence_speed; } protected static function intel_current_sequence_count() { $count = 0; $i915_gem_seqno = file_get_contents('/sys/kernel/debug/dri/0/i915_gem_seqno'); $current_sequence = strpos($i915_gem_seqno, 'Current sequence (render ring): '); if($current_sequence !== false) { $current_sequence = substr($i915_gem_seqno, $current_sequence + 32); $current_sequence = substr($current_sequence, 0, strpos($current_sequence, PHP_EOL)); if(is_numeric($current_sequence)) { $count = $current_sequence; } } return $count; } public static function intel_command_speed() { // Determine GPU usage $first_read = self::intel_current_sequence_count(); sleep(1); $second_read = self::intel_current_sequence_count(); return $second_read - $first_read; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/sys_v5.php0000644000175000017500000000251611564533734025115 0ustar michaelmichael. */ class sys_v5 implements phodevi_sensor { public static function get_type() { return 'sys'; } public static function get_sensor() { return 'v5-voltage'; } public static function get_unit() { return 'Volts'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } public static function read_sensor() { if(phodevi::is_linux()) { $sensor = phodevi_linux_parser::read_sensors(array('V5', '+5V')); } else { $sensor = -1; } return $sensor; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/sys_v3.php0000644000175000017500000000252211564533734025110 0ustar michaelmichael. */ class sys_v3 implements phodevi_sensor { public static function get_type() { return 'sys'; } public static function get_sensor() { return 'v3-voltage'; } public static function get_unit() { return 'Volts'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } public static function read_sensor() { if(phodevi::is_linux()) { $sensor = phodevi_linux_parser::read_sensors(array('V3.3', '+3.3V')); } else { $sensor = -1; } return $sensor; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/sys_v12.php0000644000175000017500000000252211564533734025170 0ustar michaelmichael. */ class sys_v12 implements phodevi_sensor { public static function get_type() { return 'sys'; } public static function get_sensor() { return 'v12-voltage'; } public static function get_unit() { return 'Volts'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } public static function read_sensor() { if(phodevi::is_linux()) { $sensor = phodevi_linux_parser::read_sensors(array('V12', '+12V')); } else { $sensor = -1; } return $sensor; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/sys_iowait.php0000644000175000017500000000347211564533734026061 0ustar michaelmichael. */ class sys_iowait implements phodevi_sensor { public static function get_type() { return 'sys'; } public static function get_sensor() { return 'iowait'; } public static function get_unit() { return 'Percent'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } 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; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/sys_fanspeed.php0000644000175000017500000000334611564533734026352 0ustar michaelmichael. */ class sys_fanspeed implements phodevi_sensor { public static function get_type() { return 'sys'; } public static function get_sensor() { return 'fan-speed'; } public static function get_unit() { return 'RPMs'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } public static function read_sensor() { $fan_speed = -1; if(phodevi::is_linux()) { $raw_fan = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/device/fan2_input', 'POSITIVE_NUMERIC'); if($raw_fan == -1) { $raw_fan = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/device/fan3_input', 'POSITIVE_NUMERIC'); } if($raw_fan == -1) { $raw_fan = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/device/fan4_input', 'POSITIVE_NUMERIC'); } if($raw_fan != -1) { $fan_speed = $raw_fan; } } return $fan_speed; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/swap_usage.php0000644000175000017500000000235211564533734026021 0ustar michaelmichael. */ class swap_usage implements phodevi_sensor { public static function get_type() { return 'swap'; } public static function get_sensor() { return 'usage'; } public static function get_unit() { return 'Megabytes'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } public static function read_sensor() { return memory_usage::mem_usage('SWAP', 'USED'); } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/hdd_write_speed.php0000644000175000017500000000315611564533734027017 0ustar michaelmichael. */ class hdd_write_speed implements phodevi_sensor { public static function get_type() { return 'hdd'; } public static function get_sensor() { return 'write-speed'; } public static function get_unit() { return 'MB/s'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } public static function read_sensor() { // speed in MB/s $speed = -1; if(phodevi::is_linux()) { static $sys_disk = null; if($sys_disk == null) { foreach(pts_file_io::glob('/sys/class/block/sd*/stat') as $check_disk) { if(pts_file_io::file_get_contents($check_disk) != null) { $sys_disk = $check_disk; break; } } } $speed = phodevi_linux_parser::read_sys_disk_speed($sys_disk, 'WRITE'); } return $speed; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/hdd_temp.php0000644000175000017500000000233711564533734025452 0ustar michaelmichael. */ class hdd_temp implements phodevi_sensor { public static function get_type() { return 'hdd'; } public static function get_sensor() { return 'temp'; } public static function get_unit() { return 'Celsius'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } public static function read_sensor() { return phodevi_parser::read_hddtemp(null); } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/gpu_power.php0000644000175000017500000000322211565244454025666 0ustar michaelmichael. */ class gpu_power implements phodevi_sensor { public static function get_type() { return 'gpu'; } public static function get_sensor() { return 'power'; } public static function get_unit() { return 'Milliwatts'; } public static function support_check() { return self::read_sensor() > 0; } public static function read_sensor() { $gpu_power = -1; if(is_readable('/sys/kernel/debug/dri/0/i915_emon_status')) { $i915_emon_status = file_get_contents('/sys/kernel/debug/dri/0/i915_emon_status'); $power = strpos($i915_emon_status, 'Total power: '); if($power !== false) { $power = substr($i915_emon_status, $power + 13); $power = substr($power, 0, strpos($power, PHP_EOL)); if(is_numeric($power)) { if($power > 10000000) { $power /= 1000; } $gpu_power = $power; } } } return $gpu_power; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/cpu_voltage.php0000644000175000017500000000250511564533734026173 0ustar michaelmichael. */ class cpu_voltage implements phodevi_sensor { public static function get_type() { return 'cpu'; } public static function get_sensor() { return 'voltage'; } public static function get_unit() { return 'Volts'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } public static function read_sensor() { if(phodevi::is_linux()) { $sensor = phodevi_linux_parser::read_sensors('VCore'); } else { $sensor = -1; } return $sensor; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/cpu_usage.php0000644000175000017500000000562611564533734025645 0ustar michaelmichael. */ class cpu_usage implements phodevi_sensor { public static function get_type() { return 'cpu'; } public static function get_sensor() { return 'usage'; } public static function get_unit() { return 'Percent'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } 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); } private static function cpu_load_array($read_core = -1) { // CPU load array $load = array(); if(phodevi::is_linux() && is_file('/proc/stat')) { $stat = file_get_contents('/proc/stat'); if($read_core > -1 && ($l = strpos($stat, 'cpu' . $read_core)) !== false) { $start_line = $l; } else { $start_line = 0; } $stat = substr($stat, $start_line, strpos($stat, "\n")); $stat_break = explode(' ', $stat); for($i = 1; $i < 6; $i++) { array_push($load, $stat_break[$i]); } } else if(phodevi::is_bsd()) { $load = explode(' ', phodevi_bsd_parser::read_sysctl('kern.cp_time')); } return $load; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/cpu_fanspeed.php0000644000175000017500000000310611564533734026315 0ustar michaelmichael. */ class cpu_fanspeed implements phodevi_sensor { public static function get_type() { return 'cpu'; } public static function get_sensor() { return 'fan-speed'; } public static function get_unit() { return 'RPM'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } public static function read_sensor() { $fan_speed = -1; if(phodevi::is_linux()) { $raw_fan = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/device/fan1_input', 'POSITIVE_NUMERIC'); if($raw_fan == -1) { $raw_fan = phodevi_linux_parser::read_sysfs_node('/sys/class/hwmon/hwmon*/fan1_input', 'POSITIVE_NUMERIC'); } if($raw_fan != -1) { $fan_speed = $raw_fan; } } return $fan_speed; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/gpu_fanspeed.php0000644000175000017500000000336411564533734026327 0ustar michaelmichael. */ class gpu_fanspeed implements phodevi_sensor { public static function get_type() { return 'gpu'; } public static function get_sensor() { return 'fan-speed'; } public static function get_unit() { return 'Percent'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } public static function read_sensor() { // Report graphics processor fan speed as a percent $fan_speed = -1; if(phodevi::is_nvidia_graphics()) { // NVIDIA fan speed reading support in NVIDIA 190.xx and newer // TODO: support for multiple fans, also for reading GPUFanTarget to get appropriate fan // nvidia-settings --describe GPUFanTarget $fan_speed = phodevi_parser::read_nvidia_extension('[fan:0]/GPUCurrentFanSpeed'); } else if(phodevi::is_ati_graphics() && phodevi::is_linux()) { $fan_speed = phodevi_linux_parser::read_ati_overdrive('FanSpeed'); } return $fan_speed; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/hdd_read_speed.php0000644000175000017500000000316011564533734026573 0ustar michaelmichael. */ class hdd_read_speed implements phodevi_sensor { public static function get_type() { return 'hdd'; } public static function get_sensor() { return 'read-speed'; } public static function get_unit() { return 'MB/s'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } public static function read_sensor() { // speed in MB/s $speed = -1; if(phodevi::is_linux()) { static $sys_disk = null; if($sys_disk == null) { foreach(pts_file_io::glob('/sys/class/block/sd*/stat') as $check_disk) { if(pts_file_io::file_get_contents($check_disk) != null) { $sys_disk = $check_disk; break; } } } $speed = phodevi_linux_parser::read_sys_disk_speed($sys_disk, 'READ'); } return $speed; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/cpu_power.php0000644000175000017500000000373411647631622025670 0ustar michaelmichael. */ class cpu_power implements phodevi_sensor { public static function get_type() { return 'cpu'; } public static function get_sensor() { return 'power'; } public static function get_unit() { return 'Watts'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } public static function read_sensor() { // Read the processor power consumption (not the overall system power consumption exposed by sys.power sensor) $cpu_watts = -1; if(phodevi::is_linux()) { // 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; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/memory_usage.php0000644000175000017500000000764312153134541026353 0ustar michaelmichael. */ class memory_usage implements phodevi_sensor { private static $page_size = -1; public static function get_type() { return 'memory'; } public static function get_sensor() { return 'usage'; } public static function get_unit() { return 'Megabytes'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } public static function read_sensor() { return memory_usage::mem_usage('MEMORY', 'USED'); } public static function mem_usage($TYPE = 'TOTAL', $READ = 'USED') { // Reads system memory usage $mem_usage = -1; if(pts_client::executable_in_path('free') != false) { $mem = explode("\n", shell_exec('free -t -m 2>&1')); $grab_line = null; $buffers_and_cache = 0; for($i = 0; $i < count($mem); $i++) { $line_parts = pts_strings::colon_explode($mem[$i]); if(count($line_parts) == 2) { $line_type = $line_parts[0]; if($TYPE == 'MEMORY' && $line_type == 'Mem') { $grab_line = $line_parts[1]; } else if($TYPE == 'SWAP' && $line_type == 'Swap') { $grab_line = $line_parts[1]; } else if($TYPE == 'TOTAL' && $line_type == 'Total') { $grab_line = $line_parts[1]; } else if($line_type == '-/+ buffers/cache' && $TYPE != 'SWAP') { $buffers_and_cache = pts_arrays::first_element(explode(' ', pts_strings::trim_spaces($line_parts[1]))); } } } if(!empty($grab_line)) { $grab_line = pts_strings::trim_spaces($grab_line); $mem_parts = explode(' ', $grab_line); if($READ == 'USED') { if(count($mem_parts) >= 2 && is_numeric($mem_parts[1])) { $mem_usage = $mem_parts[1] - $buffers_and_cache; } } else if($READ == 'TOTAL') { if(count($mem_parts) >= 1 && is_numeric($mem_parts[0])) { $mem_usage = $mem_parts[0]; } } else if($READ == 'FREE') { if(count($mem_parts) >= 3 && is_numeric($mem_parts[2])) { $mem_usage = $mem_parts[2]; } } } } else if(pts_client::executable_in_path('vm_stat') != false) { $vmstats = explode("\n", shell_exec('vm_stat 2>&1')); $grab_line = null; // 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; } } } $mem_usage = pts_math::set_precision($mem_usage); } return $mem_usage; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/network_usage.php0000664000175000017500000000404212153135573026532 0ustar michaelmichael&1')); $ibytes_index = -1; $obytes_index = -1; $ibytes = -1; $obytes = -1; foreach($netstat_lines as $line) { if(strtok($line, ' ') == 'Name') { $ibytes_index = strpos($line, 'Ierrs') + 6; $obytes_index = strpos($line, 'Oerrs') + 6; continue; } //$netstat_data = pts_strings::trim_explode(' ', $line); /* * Sample output: * Name Mtu Network Address Ipkts Ierrs Ibytes Opkts Oerrs Obytes Coll * en0 1500 00:25:4b:c5:95:66 23350 0 19111634 13494 0 1632167 0 */ if(strtok($line, ' ') == $IFACE) { $ibytes = strtok(substr($line, $ibytes_index), ' '); $obytes = strtok(substr($line, $obytes_index), ' '); $net_counter = $ibytes + $obytes; } if($ibytes != -1 && $obytes != -1) break; } } return $net_counter; } public static function read_sensor() { //chosen iterface - redo this if parameterized sensors become possible $iface = 'en0'; $net_speed = -1; if(self::$timestamp_old = -1) { self::$counter_old = self::net_counter($iface); self::$timestamp_old = time(); sleep(1); } $counter_new = self::net_counter($iface); $timestamp_new = time(); $net_speed = (($counter_new - self::$counter_old) >> 10) / ($timestamp_new - self::$timestamp_old); return $net_speed; } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/cpu_freq.php0000644000175000017500000000517512157172525025471 0ustar michaelmichael. */ class cpu_freq implements phodevi_sensor { public static function get_type() { return 'cpu'; } public static function get_sensor() { return 'freq'; } public static function get_unit() { return 'Megahertz'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } 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')) // fall back for those without cpufreq { $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); } } ?> phoronix-test-suite/pts-core/objects/phodevi/sensors/gpu_temp.php0000644000175000017500000000504712163306752025501 0ustar michaelmichael. */ class gpu_temp implements phodevi_sensor { public static function get_type() { return 'gpu'; } public static function get_sensor() { return 'temp'; } public static function get_unit() { return 'Celsius'; } public static function support_check() { $test = self::read_sensor(); return is_numeric($test) && $test != -1; } public static function read_sensor() { // Report graphics processor temperature $temp_c = -1; if(phodevi::is_nvidia_graphics()) { $temp_c = phodevi_parser::read_nvidia_extension('GPUCoreTemp'); } else if(phodevi::is_ati_graphics() && phodevi::is_linux()) { $temp_c = phodevi_linux_parser::read_ati_overdrive('Temperature'); } else { foreach(array_merge(array('/sys/class/drm/card0/device/temp1_input'), pts_file_io::glob('/sys/class/drm/card0/device/hwmon/hwmon*/temp1_input')) as $temp_input) { // This works for at least Nouveau driver with Linux 2.6.37 era DRM if(is_readable($temp_input) == false) { continue; } $temp_input = pts_file_io::file_get_contents($temp_input); if(is_numeric($temp_input)) { if($temp_input > 1000) { $temp_input /= 1000; } $temp_c = $temp_input; break; } } if($temp_c == -1 && is_readable('/sys/kernel/debug/dri/0/i915_emon_status')) { // Intel thermal $i915_emon_status = file_get_contents('/sys/kernel/debug/dri/0/i915_emon_status'); $temp = strpos($i915_emon_status, 'GMCH temp: '); if($temp !== false) { $temp = substr($i915_emon_status, $temp + 11); $temp = substr($temp, 0, strpos($temp, PHP_EOL)); if(is_numeric($temp) && $temp > 0) { $temp_c = $temp; } } } } if($temp_c > 1000) { return -1; } return $temp_c; } } ?> phoronix-test-suite/pts-core/objects/phodevi/components/phodevi_network.php0000644000175000017500000000357111670727327027570 0ustar michaelmichael. */ class phodevi_network extends phodevi_device_interface { public static function read_property($identifier) { switch($identifier) { case 'identifier': $property = new phodevi_device_property('network_device_string', phodevi::smart_caching); break; } return $property; } public static function network_device_string() { $network = array(); if(phodevi::is_macosx()) { // TODO: implement } else if(phodevi::is_bsd()) { foreach(array('dev.em.0.%desc', 'dev.wpi.0.%desc', 'dev.mskc.0.%desc') as $controller) { $pci = phodevi_bsd_parser::read_sysctl($controller); if(!empty($pci)) { array_push($network, $pci); } } } else if(phodevi::is_windows()) { // TODO: implement } else if(phodevi::is_linux()) { foreach(array('Ethernet controller', 'Network controller') as $controller) { $pci = phodevi_linux_parser::read_pci($controller); if(!empty($pci)) { array_push($network, $pci); } } } return implode(' + ', $network); } } ?> phoronix-test-suite/pts-core/objects/phodevi/components/phodevi_audio.php0000644000175000017500000000461011621613605027160 0ustar michaelmichael. */ class phodevi_audio extends phodevi_device_interface { public static function read_property($identifier) { switch($identifier) { case 'identifier': $property = new phodevi_device_property('audio_processor_string', phodevi::smart_caching); break; } return $property; } public static function audio_processor_string() { $audio = null; if(phodevi::is_macosx()) { // TODO: implement } else if(phodevi::is_bsd()) { foreach(array('dev.hdac.0.%desc') as $dev) { $dev = phodevi_bsd_parser::read_sysctl($dev); if(!empty($dev)) { $audio = $dev; } } } else if(phodevi::is_windows()) { // TODO: implement } else if(phodevi::is_linux()) { foreach(pts_file_io::glob('/sys/class/sound/card*/hwC0D*/vendor_name') as $vendor_name) { $card_dir = dirname($vendor_name) . '/'; if(!is_readable($card_dir . 'chip_name')) { continue; } $vendor_name = pts_file_io::file_get_contents($vendor_name); $chip_name = pts_file_io::file_get_contents($card_dir . 'chip_name'); $audio = $vendor_name . ' '. $chip_name; if(strpos($chip_name, 'HDMI') === false) { // If HDMI is in the audio string, likely the GPU-provided audio, so try to find the mainboard otherwise $chip = null; break; } } if($audio == null) { $audio = phodevi_linux_parser::read_pci('Multimedia audio controller'); } if($audio == null) { $audio = phodevi_linux_parser::read_pci('Audio device'); } } return $audio; } } ?> phoronix-test-suite/pts-core/objects/phodevi/components/phodevi_motherboard.php0000644000175000017500000003145711740702040030370 0ustar michaelmichael. */ class phodevi_motherboard extends phodevi_device_interface { public static function read_property($identifier) { switch($identifier) { case 'identifier': $property = new phodevi_device_property('motherboard_string', phodevi::smart_caching); break; case 'serial-number': $property = new phodevi_device_property('serial_number', phodevi::smart_caching); break; case 'power-mode': $property = new phodevi_device_property('power_mode', phodevi::smart_caching); break; case 'pci-devices': $property = new phodevi_device_property('pci_devices', phodevi::smart_caching); break; case 'usb-devices': $property = new phodevi_device_property('usb_devices', phodevi::std_caching); break; } return $property; } public static function usb_devices() { $usb = array(); if(phodevi::is_linux()) { foreach(pts_file_io::glob('/sys/bus/usb/devices/*-*/manufacturer') as $usb_dir) { $usb_dir = dirname($usb_dir) . '/'; if(!is_file($usb_dir . 'product') || !is_file($usb_dir . 'idProduct') || !is_file($usb_dir . 'idVendor')) { continue; } $vendor = pts_strings::trim_search_query(pts_strings::strip_string(pts_file_io::file_get_contents($usb_dir . 'manufacturer'))); $device = pts_strings::trim_search_query(pts_strings::strip_string(str_replace($vendor, null, pts_file_io::file_get_contents($usb_dir . 'product')))); $device = pts_strings::keep_in_string($device, pts_strings::CHAR_LETTER | pts_strings::CHAR_NUMERIC | pts_strings::CHAR_DECIMAL | pts_strings::CHAR_SPACE | pts_strings::CHAR_DASH | pts_strings::CHAR_UNDERSCORE | pts_strings::CHAR_COLON | pts_strings::CHAR_COMMA); if($vendor == null || $device == null || $vendor == 'Generic') { continue; } array_push($usb, array( 'Class' => pts_file_io::file_get_contents($usb_dir . 'bDeviceClass'), 'Vendor' => $vendor, 'Device' => $device, 'VendorID' => pts_file_io::file_get_contents($usb_dir . 'idVendor'), 'DeviceID' => pts_file_io::file_get_contents($usb_dir . 'idProduct') )); } } return $usb; } public static function is_genuine($mobo) { return strpos($mobo, ' ') > 1 && !pts_strings::has_in_istring($mobo, array('Virtual', 'Bochs', '440BX', 'Megatrends', 'Award ', 'Software', 'Xen', 'HVM ', 'Notebook', 'OEM ', ' KVM', 'unknown')) && !is_numeric(substr($mobo, 0, strpos($mobo, ' '))); // pts_strings::string_contains($mobo, pts_strings::CHAR_NUMERIC); } public static function pci_devices() { $pci_devices = array(); if(phodevi::is_linux() && isset(phodevi::$vfs->lspci)) { $lspci = phodevi::$vfs->lspci; $lspci = explode("\n\n", $lspci); foreach($lspci as $o => &$lspci_section) { $lspci_section = explode("\n", $lspci_section); $formatted_section = array(); foreach($lspci_section as $i => &$line) { $line = explode(':', $line); if(count($line) == 2 && in_array($line[0], array('Class', 'Vendor', 'Device', 'Driver', 'Rev', 'Module'))) { $line[1] = trim($line[1]); if(($c = strrpos($line[1], ' [')) !== false) { $id = substr($line[1], ($c + 2)); $id = '0x' . substr($id, 0, strpos($id, ']')); switch($line[0]) { case 'Vendor': $formatted_section['VendorID'] = $id; break; case 'Device': $formatted_section['DeviceID'] = $id; break; } $line[1] = substr($line[1], 0, $c); } if($line[0] == 'Class') { switch($line[1]) { case 'Ethernet controller': case 'Network controller': $line[1] = 'Network'; break; case 'VGA compatible controller': $line[1] = 'GPU'; break; case 'Audio device': case 'Multimedia audio controller': $line[1] = 'Audio'; break; // case 'RAM memory': // case 'Host bridge': // $line[1] = 'Chipset'; // break; default: $line[1] = null; break; } } else if($line[0] == 'Device' || $line[0] == 'Vendor') { $line[1] = pts_strings::trim_search_query(pts_strings::strip_string($line[1])); $line[1] = pts_strings::keep_in_string($line[1], pts_strings::CHAR_LETTER | pts_strings::CHAR_NUMERIC | pts_strings::CHAR_DECIMAL | pts_strings::CHAR_SPACE | pts_strings::CHAR_DASH | pts_strings::CHAR_UNDERSCORE | pts_strings::CHAR_COLON | pts_strings::CHAR_COMMA); } $formatted_section[$line[0]] = $line[1]; } } if(count($formatted_section) > 0 && $formatted_section['Class'] != null) { array_push($pci_devices, $formatted_section); } } } return $pci_devices; } public static function parse_pci_device_data(&$lspci, &$dmesg, $ignore_external_pci_devices = false) { $pci_devices = explode(PHP_EOL . PHP_EOL, $lspci); $sanitized_devices = array(); foreach($pci_devices as &$device) { $device .= PHP_EOL; $location = substr($device, 0, strpos($device, ' ')); if(!strpos($location, ':') || !strpos($location, '.')) { // If it's not a valid PCI bus location (i.e. XX:YY.Z), it's probably not formatted well or wrong continue; } $class = substr($device, ($s = (strpos($device, '[') + 1)), (strpos($device, ']', $s) - $s)); if(!(isset($class[3]) && !isset($class[4]))) { // class must be 4 characters: 2 for class, 2 for sub-class continue; } // 0300 is GPUs if($ignore_external_pci_devices && in_array($class, array('0300'))) { // Don't report external PCI devices continue; } $device_class = substr($class, 0, 2); $sub_class = substr($class, 2, 2); $device_name = substr($device, ($l = strpos($device, ']:') + 3), ($s = strpos($device, ':', $l)) - $l); $device_name = substr($device_name, 0, strrpos($device_name, ' [')); $device_name = str_replace('/', '-', str_replace(array('[AMD]', '[SiS]'), null, $device_name)); $device_name = pts_strings::strip_string($device_name); if($device_name == null || strpos($device_name, ' ') === false) { // it must be junk not worth reporting continue; } $temp = substr($device, $s - 5); if($temp[0] != '[' || $temp[10] != ']') { continue; } $vendor_id = substr($temp, 1, 4); $device_id = substr($temp, 6, 4); $drivers = array(); if(($s = strpos($device, 'Kernel driver in use:')) !== false) { $temp = substr($device, ($s = $s + 22), (strpos($device, PHP_EOL, $s) - $s)); if($temp != null) { array_push($drivers, $temp); } } if(($s = strpos($device, 'Kernel modules:')) !== false) { $temp = substr($device, ($s = $s + 16), (strpos($device, PHP_EOL, $s) - $s)); if($temp != null) { foreach(explode(' ', trim($temp)) as $temp) { $temp = str_replace(',', null, $temp); if($temp != null && !in_array($temp, $drivers)) { array_push($drivers, $temp); } } } } if(empty($drivers)) { // If there's no drivers, nothing to report continue; } if(!in_array($vendor_id . ':' . $device_id, array_keys($sanitized_devices))) { $dmesg_example = array(); if($dmesg != null) { foreach($drivers as $driver) { $offset = 1; while($offset != false && ($offset = strpos($dmesg, $driver, $offset)) !== false) { $line = substr($dmesg, 0, strpos($dmesg, "\n", $offset)); $line = substr($line, strrpos($line, "\n")); $line = trim(substr($line, strpos($line, '] ') + 2)); if($line != null && !isset($line[128])) { array_push($dmesg_example, $line); } $offset = strpos($dmesg, "\n", ($offset + 1)); } } } $sanitized_devices[$vendor_id . ':' . $device_id] = array( $vendor_id, $device_id, $device_name, $device_class, $sub_class, $drivers, trim($device), implode(PHP_EOL, $dmesg_example) ); } } return $sanitized_devices; } public static function power_mode() { // Returns the power mode $return_status = null; if(phodevi::is_linux()) { $sysfs_checked = false; foreach(pts_file_io::glob('/sys/class/power_supply/AC*/online') as $online) { if(pts_file_io::file_get_contents($online) == '0') { $return_status = 'This computer was running on battery power'; break; } $sysfs_checked = true; } if(!$sysfs_checked) { // There likely was no sysfs power_supply support for that power adapter $power_state = phodevi_linux_parser::read_acpi('/ac_adapter/AC/state', 'state'); if($power_state == 'off-line') { $return_status = 'This computer was running on battery power'; } } } return $return_status; } public static function serial_number() { $serial = null; if(phodevi::is_linux()) { $serial = phodevi_linux_parser::read_dmidecode('system', 'System Information', 'Serial Number', true, array()); } return $serial; } public static function motherboard_string() { // Returns the motherboard / system model name or number $info = null; if(phodevi::is_macosx()) { $info = phodevi_osx_parser::read_osx_system_profiler('SPHardwareDataType', 'ModelName'); } else if(phodevi::is_solaris()) { $manufacturer = phodevi_solaris_parser::read_sun_ddu_dmi_info(array('MotherBoardInformation,Manufacturer', 'SystemInformation,Manufacturer')); $product = phodevi_solaris_parser::read_sun_ddu_dmi_info(array('MotherBoardInformation,Product', 'SystemInformation,Product', 'SystemInformation,Model')); if(count($manufacturer) == 1 && count($product) == 1) { $info = $manufacturer[0] . ' ' . $product[0]; } } else if(phodevi::is_bsd()) { $vendor = phodevi_bsd_parser::read_kenv('smbios.system.maker'); $product = phodevi_bsd_parser::read_kenv('smbios.system.product'); $version = phodevi_bsd_parser::read_kenv('smbios.system.version'); // for at least Lenovo ThinkPads this is where it displays ThinkPad model if($vendor != null && ($product != null || $version != null)) { $info = $vendor . ' ' . $product . ' ' . $version; } else if(($vendor = phodevi_bsd_parser::read_sysctl('hw.vendor')) != false && ($version = phodevi_bsd_parser::read_sysctl(array('hw.version', 'hw.product'))) != false) { $info = trim($vendor . ' ' . $version); } else if(($acpi = phodevi_bsd_parser::read_sysctl('dev.acpi.0.%desc')) != false) { $info = trim($acpi); } } else if(phodevi::is_linux()) { $vendor = phodevi_linux_parser::read_sys_dmi(array('board_vendor', 'sys_vendor')); $name = phodevi_linux_parser::read_sys_dmi(array('board_name', 'product_name')); $version = phodevi_linux_parser::read_sys_dmi(array('board_version', 'product_version')); if($vendor != false && $name != false) { $info = strpos($name . ' ', $vendor . ' ') === false ? $vendor . ' ' : null; $info .= $name; if($version != false && strpos($info, $version) === false && pts_strings::string_only_contains($version, pts_strings::CHAR_NUMERIC | pts_strings::CHAR_DECIMAL)) { $info .= (substr($version, 0, 1) == 'v' ? ' ' : ' v') . $version; } } if(empty($info)) { if($info == null) { $hw_string = phodevi_linux_parser::read_cpuinfo('Hardware'); if(count($hw_string) == 1) { $info = $hw_string[0]; } } $bios_vendor = phodevi_linux_parser::read_sys_dmi('bios_vendor'); $bios_version = phodevi_linux_parser::read_sys_dmi('bios_version'); if($bios_vendor != null) { $info = $bios_vendor . ' ' . $bios_version; } } if(empty($info)) { $info = phodevi_linux_parser::read_sys_dmi('product_name'); } } else if(phodevi::is_windows()) { $info = phodevi_windows_parser::read_cpuz('Mainboard Model', null); } if((strpos($info, 'Mac ') !== false || strpos($info, 'MacBook') !== false) && strpos($info, 'Apple') === false) { $info = 'Apple ' . $info; } // ensure words aren't repeated (e.g. VMware VMware Virtual and MSI MSI X58M (MS-7593)) $info = implode(' ', array_unique(explode(' ', $info))); return $info; } } ?> phoronix-test-suite/pts-core/objects/phodevi/components/phodevi_disk.php0000644000175000017500000002301112152754411027006 0ustar michaelmichael. */ class phodevi_disk extends phodevi_device_interface { public static function read_property($identifier) { switch($identifier) { case 'identifier': $property = new phodevi_device_property('hdd_string', phodevi::smart_caching); break; case 'scheduler': $property = new phodevi_device_property('hdd_scheduler', phodevi::no_caching); break; case 'mount-options': $property = new phodevi_device_property('proc_mount_options', phodevi::no_caching); break; } return $property; } public static function device_notes() { $notes = array(); if(($disk_scheduler = phodevi::read_property('disk', 'scheduler')) != null) { array_push($notes, 'Disk Scheduler: ' . $disk_scheduler); } return $notes; } public static function proc_mount_options($mount_point = null, $mounts = null) { $mount_options = false; if($mount_point == null && PTS_IS_CLIENT) { $mount_point = pts_client::test_install_root_path(); } if($mounts == null && isset(phodevi::$vfs->mounts)) { $mounts = phodevi::$vfs->mounts; } do { $mount_point = dirname($mount_point); } while(($p = strrpos($mounts, ' ' . $mount_point . ' ')) === false && $mount_point != null && $mount_point != '/'); if($p) { if(($x = strrpos($mounts, PHP_EOL, (0 - strlen($mounts) + $p))) !== false) { $mounts = trim(substr($mounts, $x)); } if(($x = strpos($mounts, PHP_EOL)) !== false) { $mounts = substr($mounts, 0, $x); } $mounts = explode(' ', $mounts); if(isset($mounts[4]) && $mounts[1] == $mount_point && substr($mounts[0], 0, 1) == '/') { // Sort mount options alphabetically so it's easier to look at... $mounts[3] = explode(',', $mounts[3]); sort($mounts[3]); $mounts[3] = implode(',', $mounts[3]); $mount_options = array( 'device' => $mounts[0], 'mount-point' => $mounts[1], 'file-system' => $mounts[2], 'mount-options' => $mounts[3] ); } } return $mount_options; } public static function is_genuine($disk) { return strpos($disk, ' ') > 1 && !pts_strings::has_in_istring($disk, array('VBOX', 'QEMU', 'Virtual')); // pts_strings::string_contains($mobo, pts_strings::CHAR_NUMERIC); } public static function hdd_string() { $disks = array(); if(phodevi::is_macosx()) { // TODO: Support reading non-SATA drives and more than one drive $capacity = phodevi_osx_parser::read_osx_system_profiler('SPSerialATADataType', 'Capacity'); $model = phodevi_osx_parser::read_osx_system_profiler('SPSerialATADataType', 'Model'); if(($cut = strpos($capacity, ' (')) !== false) { $capacity = substr($capacity, 0, $cut); } if(($cut = strpos($capacity, ' ')) !== false) { if(is_numeric(substr($capacity, 0, $cut))) { $capacity = floor(substr($capacity, 0, $cut)) . substr($capacity, $cut); } } $capacity = str_replace(' GB', 'GB', $capacity); if(!empty($capacity) && !empty($model)) { $disks = array($capacity . ' ' . $model); } } else if(phodevi::is_bsd()) { $i = 0; do { $disk = phodevi_bsd_parser::read_sysctl('dev.ad.' . $i . '.%desc'); if($disk != false && strpos($disk, 'DVD') === false && strpos($disk, 'ATAPI') === false) { array_push($disks, $disk); } $i++; } while(($disk != false || $i < 9) && $i < 128); // On some systems, the first drive seems to be at dev.ad.8 rather than starting at dev.ad.0 if(empty($disks) && pts_client::executable_in_path('camcontrol')) { $camcontrol = trim(shell_exec('camcontrol devlist 2>&1')); foreach(explode(PHP_EOL, $camcontrol) as $line) { if(substr($line, 0, 1) == '<' && ($model_end = strpos($line, '>')) !== false && strpos($line, 'DVD') === false && strpos($line, 'ATAPI') === false) { $disk = self::prepend_disk_vendor(substr($line, 1, ($model_end - 1))); array_push($disks, $disk); } } } } else if(phodevi::is_solaris()) { if(is_executable('/usr/ddu/bin/i386/hd_detect')) { $hd_detect = explode(PHP_EOL, trim(shell_exec('/usr/ddu/bin/i386/hd_detect -l 2>&1'))); foreach($hd_detect as $hd_line) { if(isset($hd_line) && ($hd_pos = strpos($hd_line, ':/')) != false) { $disk = trim(substr($hd_line, 0, $hd_pos)); $disk = self::prepend_disk_vendor($disk); if($disk != 'blkdev') { array_push($disks, $disk); } } } } } else if(phodevi::is_linux()) { $disks_formatted = array(); $disks = array(); foreach(array_merge(pts_file_io::glob('/sys/block/sd*'), pts_file_io::glob('/sys/block/mmcblk*')) as $sdx) { if(strpos($sdx, 'boot') !== false) { // Don't include devices like /sys/block/mmcblk0boot[0,1] as it's repeat of /sys/block/mmcblk0 continue; } if((is_file($sdx . '/device/name') || is_file($sdx . '/device/model')) && is_file($sdx . '/size')) { $disk_size = pts_file_io::file_get_contents($sdx . '/size'); $disk_model = pts_file_io::file_get_contents($sdx . (is_file($sdx . '/device/model') ? '/device/model' : '/device/name')); $disk_removable = pts_file_io::file_get_contents($sdx . '/removable'); if($disk_removable == '1') { // Don't count removable disks continue; } $disk_size = round($disk_size * 512 / 1000000000) . 'GB'; $disk_model = self::prepend_disk_vendor($disk_model); if(strpos($disk_model, $disk_size . ' ') === false && strpos($disk_model, ' ' . $disk_size) === false && $disk_size != '1GB') { $disk_model = $disk_size . ' ' . $disk_model; } if($disk_size > 0) { array_push($disks_formatted, $disk_model); } } } for($i = 0; $i < count($disks_formatted); $i++) { if(!empty($disks_formatted[$i])) { $times_found = 1; for($j = ($i + 1); $j < count($disks_formatted); $j++) { if($disks_formatted[$i] == $disks_formatted[$j]) { $times_found++; $disks_formatted[$j] = ''; } } $disk = ($times_found > 1 ? $times_found . ' x ' : null) . $disks_formatted[$i]; array_push($disks, $disk); } } } if(count($disks) == 0) { $root_disk_size = ceil(disk_total_space('/') / 1073741824); $pts_disk_size = ceil(disk_total_space(pts_client::test_install_root_path()) / 1073741824); if($pts_disk_size > $root_disk_size) { $root_disk_size = $pts_disk_size; } if($root_disk_size > 1) { $disks = $root_disk_size . 'GB'; } else { $disks = null; } } else { $disks = implode(' + ', $disks); } return $disks; } protected static function prepend_disk_vendor($disk_model) { if(isset($disk_model[4])) { $disk_manufacturer = null; $third_char = substr($disk_model, 2, 1); switch(substr($disk_model, 0, 2)) { case 'WD': $disk_manufacturer = 'Western Digital'; if(substr($disk_model, 0, 4) == 'WDC ') { $disk_model = substr($disk_model, 4); } break; case 'MK': $disk_manufacturer = 'Toshiba'; break; case 'HD': if($third_char == 'T') { $disk_manufacturer = 'Hitachi'; } break; case 'HT': $disk_manufacturer = 'Hitachi'; break; case 'HM': case 'HN': // HM and HN appear to be Samsung series $disk_manufacturer = 'Samsung'; break; case 'ST': if($third_char == 'T') { $disk_manufacturer = 'Super Talent'; } else if($third_char != 'E') { $disk_manufacturer = 'Seagate'; } break; } if($disk_manufacturer != null && strpos($disk_model, $disk_manufacturer) === false) { $disk_model = $disk_manufacturer . ' ' . $disk_model; } // OCZ SSDs aren't spaced $disk_model = str_replace('OCZ-', 'OCZ ', $disk_model); } return $disk_model; } public static function hdd_scheduler() { $scheduler = null; $device = self::proc_mount_options(); $device = basename($device['device']); if(is_readable('/sys/block/' . ($d = pts_strings::keep_in_string($device, pts_strings::CHAR_LETTER)) . '/queue/scheduler')) { $scheduler = '/sys/block/' . $d . '/queue/scheduler'; } else if(is_link(($device = '/dev/disk/by-uuid/' . $device))) { // Go from the disk UUID to the device $device = pts_strings::keep_in_string(basename(readlink($device)), pts_strings::CHAR_LETTER); if(is_readable('/sys/block/' . $device . '/queue/scheduler')) { $scheduler = '/sys/block/' . $device . '/queue/scheduler'; } } if($scheduler) { $scheduler = pts_file_io::file_get_contents($scheduler); if(($s = strpos($scheduler, '[')) !== false && ($e = strpos($scheduler, ']', $s)) !== false) { $scheduler = strtoupper(substr($scheduler, ($s + 1), ($e - $s - 1))); } } return $scheduler; } } ?> phoronix-test-suite/pts-core/objects/phodevi/components/phodevi_chipset.php0000644000175000017500000001020612156666700027524 0ustar michaelmichael. */ class phodevi_chipset extends phodevi_device_interface { public static function read_property($identifier) { switch($identifier) { case 'identifier': $property = new phodevi_device_property('chipset_string', phodevi::smart_caching); break; } return $property; } public static function chipset_string() { $info = false; if(phodevi::is_macosx()) { $sb_vendor = phodevi_osx_parser::read_osx_system_profiler('SPSerialATADataType', 'Vendor'); $sb_product = phodevi_osx_parser::read_osx_system_profiler('SPSerialATADataType', 'Product'); if($sb_product == 'SSD') { $sb_product = null; } if(($cut_point = strpos($sb_product, ' ')) > 0) { $sb_product = substr($sb_product, 0, $cut_point); } // TODO: Can't find Northbridge $info = $sb_vendor . ' ' . $sb_product; } else if(phodevi::is_windows()) { $info = phodevi_windows_parser::read_cpuz('Northbridge', null); if($info != null) { if(($e = strpos($info, 'rev')) !== false) { $info = substr($info, 0, $e); } $info = trim($info); } } else if(phodevi::is_solaris()) { // Vendor Detection $vendor_possible_udis = array( '/org/freedesktop/Hal/devices/pci_0_0/pci_ide_3_2_0', '/org/freedesktop/Hal/devices/pci_0_0/pci_ide_1f_1_1', ); $info = phodevi_solaris_parser::read_hal_property($vendor_possible_udis, 'info.vendor'); // TODO: Northbridge and Southbridge Detection For Solaris } else if(phodevi::is_linux() || phodevi::is_hurd()) { $info = phodevi_linux_parser::read_pci(array('RAM memory', 'Host bridge')); if(count(explode(' ', $info)) == 1) { $bridge = phodevi_linux_parser::read_pci(array('Bridge', 'PCI bridge')); if(!empty($bridge)) { $match = false; $break_words = array('Ethernet', 'PCI', 'High', 'USB'); for($i = 0; $i < count($break_words) && !$match; $i++) { if(($pos = strpos($bridge, $break_words[$i])) > 0) { $bridge = trim(substr($bridge, 0, $pos)); $info = $bridge; $match = true; } } } } if(!isset($bridge) || !empty($bridge)) { // Attempt to detect Southbridge (if applicable) $southbridge = phodevi_linux_parser::read_pci(array('ISA bridge', 'SATA controller'), false); $southbridge_clean = null; if(($start_cut = strpos($southbridge, '(')) > 0 && ($end_cut = strpos($southbridge, ')', $start_cut + 1)) > 0) { $southbridge_extract = substr($southbridge, $start_cut + 1, $end_cut - $start_cut - 1); if(strpos($southbridge_extract, 'rev') === false) { $southbridge_extract = explode(' ', $southbridge_extract); $southbridge_clean = $southbridge_extract[0]; } else if(($s = strpos($southbridge, 'ICH')) > 0) { $southbridge_extract = substr($southbridge, $s); $southbridge_clean = substr($southbridge_extract, 0, strpos($southbridge_extract, ' ')); } } else if(($start_cut = strpos($southbridge, 'SB')) !== false) { $southbridge_extract = substr($southbridge, $start_cut); $southbridge_clean = substr($southbridge_extract, 0, strpos($southbridge_extract, ' ')); } if(!empty($southbridge_clean) && $southbridge_clean != 'SB') { $info .= ' + ' . $southbridge_clean; } } } return $info; } } ?> phoronix-test-suite/pts-core/objects/phodevi/components/phodevi_system.php0000644000175000017500000012764212200210462027402 0ustar michaelmichael. */ class phodevi_system extends phodevi_device_interface { public static function read_property($identifier) { switch($identifier) { case 'username': $property = new phodevi_device_property('sw_username', phodevi::std_caching); break; case 'hostname': $property = new phodevi_device_property('sw_hostname', phodevi::smart_caching); break; case 'vendor-identifier': $property = new phodevi_device_property('sw_vendor_identifier', phodevi::smart_caching); break; case 'filesystem': $property = new phodevi_device_property('sw_filesystem', phodevi::no_caching); break; case 'virtualized-mode': $property = new phodevi_device_property('sw_virtualized_mode', phodevi::smart_caching); break; case 'java-version': $property = new phodevi_device_property('sw_java_version', phodevi::std_caching); break; case 'python-version': $property = new phodevi_device_property('sw_python_version', phodevi::std_caching); break; case 'wine-version': $property = new phodevi_device_property('sw_wine_version', phodevi::std_caching); break; case 'display-server': $property = new phodevi_device_property('sw_display_server', phodevi::smart_caching); break; case 'display-driver': $property = new phodevi_device_property(array('sw_display_driver', false), phodevi::smart_caching); break; case 'display-driver-string': $property = new phodevi_device_property(array('sw_display_driver', true), phodevi::smart_caching); break; case 'dri-display-driver': $property = new phodevi_device_property('sw_dri_display_driver', phodevi::smart_caching); break; case 'opengl-driver': $property = new phodevi_device_property('sw_opengl_driver', phodevi::std_caching); break; case 'opengl-vendor': $property = new phodevi_device_property('sw_opengl_vendor', phodevi::smart_caching); break; case 'desktop-environment': $property = new phodevi_device_property('sw_desktop_environment', phodevi::smart_caching); break; case 'operating-system': $property = new phodevi_device_property('sw_operating_system', phodevi::smart_caching); break; case 'os-version': $property = new phodevi_device_property('sw_os_version', phodevi::smart_caching); break; case 'kernel': $property = new phodevi_device_property('sw_kernel', phodevi::smart_caching); break; case 'kernel-architecture': $property = new phodevi_device_property('sw_kernel_architecture', phodevi::smart_caching); break; case 'kernel-string': $property = new phodevi_device_property('sw_kernel_string', phodevi::smart_caching); break; case 'kernel-parameters': $property = new phodevi_device_property('sw_kernel_parameters', phodevi::std_caching); break; case 'compiler': $property = new phodevi_device_property('sw_compiler', phodevi::std_caching); break; case 'system-layer': $property = new phodevi_device_property('sw_system_layer', phodevi::std_caching); break; case 'environment-variables': $property = new phodevi_device_property('sw_environment_variables', phodevi::std_caching); break; } return $property; } public static function sw_username() { // Gets the system user's name if(function_exists('posix_getpwuid') && function_exists('posix_getuid')) { $userinfo = posix_getpwuid(posix_getuid()); $username = $userinfo['name']; } else { $username = trim(getenv('USERNAME')); } return $username; } public static function sw_system_layer() { $layer = null; if(phodevi::is_windows() && pts_client::executable_in_path('winecfg.exe') && ($wine = phodevi::read_property('system', 'wine-version'))) { $layer = $wine; } else { // Report virtualization $layer = phodevi::read_property('system', 'virtualized-mode'); } return $layer; } public static function sw_hostname() { $hostname = 'Unknown'; if(($bin = pts_client::executable_in_path('hostname'))) { $hostname = trim(shell_exec($bin . ' 2>&1')); } else if(phodevi::is_windows()) { $hostname = getenv('USERDOMAIN'); } return $hostname; } public static function sw_vendor_identifier() { // Returns the vendor identifier used with the External Dependencies and other distro-specific features $vendor = phodevi::is_linux() ? phodevi_linux_parser::read_lsb_distributor_id() : false; if(!$vendor) { $vendor = phodevi::read_property('system', 'operating-system'); if(($spos = strpos($vendor, ' ')) > 1) { $vendor = substr($vendor, 0, $spos); } } return str_replace(array(' ', '/'), '', strtolower($vendor)); } public static function sw_filesystem() { // Determine file-system type $fs = null; if(phodevi::is_macosx()) { $fs = phodevi_osx_parser::read_osx_system_profiler('SPSerialATADataType', 'FileSystem'); } else if(phodevi::is_bsd()) { if(pts_client::executable_in_path('mount')) { $mount = shell_exec('mount 2>&1'); if(($start = strpos($mount, 'on / (')) != false) { // FreeBSD, DragonflyBSD mount formatting /* -bash-4.0$ mount ROOT on / (hammer, local) /dev/da0s1a on /boot (ufs, local) /pfs/@@-1:00001 on /var (null, local) /pfs/@@-1:00002 on /tmp (null, local) /pfs/@@-1:00003 on /usr (null, local) /pfs/@@-1:00004 on /home (null, local) /pfs/@@-1:00005 on /usr/obj (null, local) /pfs/@@-1:00006 on /var/crash (null, local) /pfs/@@-1:00007 on /var/tmp (null, local) procfs on /proc (procfs, local) */ // TODO: improve this in case there are other partitions, etc $fs = substr($mount, $start + 6); $fs = substr($fs, 0, strpos($fs, ',')); } else if(($start = strpos($mount, 'on / type')) != false) { // OpenBSD 5.0 formatting is slightly different from above FreeBSD example // TODO: improve this in case there are other partitions, etc $fs = substr($mount, $start + 10); $fs = substr($fs, 0, strpos($fs, ' ')); } } } else if(phodevi::is_hurd()) { // Very rudimentary Hurd filesystem detection support but works for at least a clean Debian GNU/Hurd EXT2 install if(pts_client::executable_in_path('mount')) { $mount = shell_exec('mount 2>&1'); if(($start = strpos($mount, 'on / type')) != false) { $fs = substr($mount, $start + 10); $fs = substr($fs, 0, strpos($fs, ' ')); if(substr($fs, -2) == 'fs') { $fs = substr($fs, 0, -2); } } } } else if(phodevi::is_linux() || phodevi::is_solaris()) { $fs = trim(shell_exec('stat ' . pts_client::test_install_root_path() . ' -L -f -c %T 2> /dev/null')); switch($fs) { case 'ext2/ext3': if(isset(phodevi::$vfs->mounts)) { $fstab = phodevi::$vfs->mounts; $fstab = str_replace('/boot ', 'IGNORE', $fstab); $using_ext2 = strpos($fstab, ' ext2') !== false; $using_ext3 = strpos($fstab, ' ext3') !== false; $using_ext4 = strpos($fstab, ' ext4') !== false; if(!$using_ext2 && !$using_ext3 && $using_ext4) { $fs = 'ext4'; } else if(!$using_ext2 && !$using_ext4 && $using_ext3) { $fs = 'ext3'; } else if(!$using_ext3 && !$using_ext4 && $using_ext2) { $fs = 'ext2'; } else if(is_dir('/proc/fs/ext4/')) { $fs = 'ext4'; } else if(is_dir('/proc/fs/ext3/')) { $fs = 'ext3'; } } break; case 'Case-sensitive Journaled HFS+': $fs = 'HFS+'; break; case 'MS-DOS FAT32': $fs = 'FAT32'; break; case 'UFSD_NTFS_COMPR': $fs = 'NTFS'; break; case 'ecryptfs': if(isset(phodevi::$vfs->mounts)) { // An easy attempt to determine what file-system is underneath ecryptfs if being compared // For now just attempt to figure out the root file-system. if(($s = strrpos(phodevi::$vfs->mounts, ' / ')) !== false) { $s = substr(phodevi::$vfs->mounts, ($s + 3)); $s = substr($s, 0, strpos($s, ' ')); if($s != null && !isset($s[18]) && $s != 'rootfs'&& pts_strings::string_only_contains($s, pts_strings::CHAR_LETTER | pts_strings::CHAR_NUMERIC)) { $fs = $s . ' (ecryptfs)'; } } } break; default: if(substr($fs, 0, 9) == 'UNKNOWN (') { $magic_block = substr($fs, 9, -1); $known_magic_blocks = array( '0x9123683e' => 'Btrfs', '0x2fc12fc1' => 'zfs', // KQ Infotech ZFS '0x482b' => 'HFS+', '0x65735546' => 'FUSE', '0x565a4653' => 'ReiserFS', '0x52345362' => 'Reiser4', '0x3434' => 'NILFS2', '0x5346414f' => 'OpenAFS', '0x47504653' => 'GPFS', '0x5941ff53' => 'YAFFS', '0xff534d42' => 'CIFS', '0x24051905' => 'UBIFS', '0x1021994' => 'TMPFS', '0x73717368' => 'SquashFS', '0xc97e8168' => 'LogFS', '0x5346544E' => 'NTFS', '0xf15f' => 'eCryptfs', '0x61756673' => 'AuFS', '0xbd00bd0' => 'Lustre', '0xaad7aaea' => 'PanFS', // Panasas FS '0xf2f52010' => 'F2FS', '0xc36400' => 'CephFS', ); foreach($known_magic_blocks as $hex => $name) { if($magic_block == $hex) { $fs = $name; break; } } } break; } if(strpos($fs, 'UNKNOWN') !== false && isset(phodevi::$vfs->mounts)) { $mounts = phodevi::$vfs->mounts; $fs_r = array(); $fs_checks = array( 'squashfs' => 'SquashFS', 'aufs' => 'AuFS', 'unionfs' => 'UnionFS' ); foreach($fs_checks as $fs_module => $fs_name) { if(strpos($mounts, $fs_module) != false) { array_push($fs_r, $fs_name); } } if(count($fs_r) > 0) { $fs = implode(' + ', $fs_r); } } } else if(phodevi::is_windows()) { return null; } if(empty($fs)) { $fs = 'Unknown'; } return $fs; } public static function sw_virtualized_mode() { // Reports if system is running virtualized $virtualized = null; $mobo = phodevi::read_name('motherboard'); $gpu = phodevi::read_name('gpu'); $cpu = phodevi::read_property('cpu', 'model'); if(strpos($cpu, 'QEMU') !== false || (is_readable('/sys/class/dmi/id/bios_vendor') && pts_file_io::file_get_contents('/sys/class/dmi/id/bios_vendor') == 'QEMU')) { $virtualized = 'QEMU'; if(strpos($cpu, 'QEMU Virtual') !== false) { $qemu_version = substr($cpu, (strrpos($cpu, ' ') + 1)); if(pts_strings::is_version($qemu_version)) { $virtualized .= ' ' . $qemu_version; } } } else if(stripos($gpu, 'VMware') !== false || (is_readable('/sys/class/dmi/id/product_name') && stripos(pts_file_io::file_get_contents('/sys/class/dmi/id/product_name'), 'VMware') !== false)) { $virtualized = 'VMware'; } else if(stripos($gpu, 'VirtualBox') !== false || stripos(phodevi::read_name('motherboard'), 'VirtualBox') !== false) { $virtualized = 'VirtualBox'; if($vbox_manage = pts_client::executable_in_path('VBoxManage')) { $vbox_manage = trim(shell_exec($vbox_manage . ' --version 2> /dev/null')); if(is_numeric(substr($vbox_manage, 0, 1))) { $virtualized .= ' ' . $vbox_manage; } } else if($modinfo = pts_client::executable_in_path('modinfo')) { $modinfo = trim(shell_exec('modinfo -F version vboxguest 2> /dev/null')); if($modinfo != null && pts_strings::is_version(str_ireplace(array('_', 'RC', 'beta'), null, $modinfo))) { $virtualized .= ' ' . $modinfo; } } } else if(is_file('/sys/class/dmi/id/sys_vendor') && pts_file_io::file_get_contents('/sys/class/dmi/id/sys_vendor') == 'Xen') { $virtualized = pts_file_io::file_get_contents('/sys/class/dmi/id/product_name'); if(strpos($virtualized, 'Xen') === false) { $virtualized = 'Xen ' . $virtualized; } // version string $virtualized .= ' ' . pts_file_io::file_get_contents('/sys/class/dmi/id/product_version'); // $virtualized should be then e.g. 'Xen HVM domU 4.1.1' } else if(stripos($gpu, 'Microsoft Hyper-V') !== false) { $virtualized = 'Microsoft Hyper-V Server'; } else if(stripos($mobo, 'Parallels Software') !== false) { $virtualized = 'Parallels Virtualization'; } else if(is_file('/sys/hypervisor/type')) { $type = pts_file_io::file_get_contents('/sys/hypervisor/type'); $version = array(); foreach(array('major', 'minor', 'extra') as $v) { if(is_file('/sys/hypervisor/version/' . $v)) { $v = pts_file_io::file_get_contents('/sys/hypervisor/version/' . $v); } else { continue; } if($v != null) { if(!empty($version) && substr($v, 0, 1) != '.') { $v = '.' . $v; } array_push($version, $v); } } $virtualized = ucwords($type) . ' ' . implode('', $version) . ' Hypervisor'; } if($systemd_virt = pts_client::executable_in_path('systemd-detect-virt')) { $systemd_virt = trim(shell_exec($systemd_virt . ' 2> /dev/null')); if($systemd_virt != null && $systemd_virt != 'none') { switch($systemd_virt) { case 'kvm': $systemd_virt = 'KVM'; break; case 'oracle': $systemd_virt = 'Oracle'; break; } if($virtualized != null && stripos($virtualized, $systemd_virt) === false && stripos($systemd_virt, $virtualized) === false) { $virtualized = $systemd_virt . ' ' . $virtualized; } else if($virtualized == null) { $virtualized = $systemd_virt; } } } return $virtualized; } public static function sw_environment_variables() { $check_variables = array('LIBGL', '__GL', 'DRI_'); $to_report = array(); if(stripos(phodevi::read_property('system', 'opengl-driver'), 'Mesa')) { array_push($check_variables, 'MESA', 'GALLIUM'); } if(isset($_SERVER)) { foreach($_SERVER as $name => &$value) { foreach($check_variables as $var) { if(stripos($name, $var) !== false) { array_push($to_report, $name . '=' . $value); break; } } } } return implode(' ', array_unique($to_report)); } public static function sw_compiler() { // Returns version of the compiler (if present) $compilers = array(); if($gcc = pts_client::executable_in_path('gcc')) { if(!is_link($gcc) || strpos(readlink($gcc), 'gcc') !== false) { // GCC // If it's a link, ensure that it's not linking to llvm/clang or something $version = trim(shell_exec('gcc -dumpversion 2>&1')); if(pts_strings::is_version($version)) { $v = shell_exec('gcc -v 2>&1'); if(($t = strrpos($v, $version . ' ')) !== false) { $v = substr($v, ($t + strlen($version) + 1)); $v = substr($v, 0, strpos($v, ' ')); if($v != null && ctype_digit($v)) { // On development versions the release date is expressed // e.g. gcc version 4.7.0 20120314 (prerelease) (GCC) $version .= ' ' . $v; } } $compilers['gcc'] = 'GCC ' . $version; } } } if(pts_client::executable_in_path('opencc')) { // Open64 $compilers['opencc'] = 'Open64 ' . trim(shell_exec('opencc -dumpversion 2>&1')); } if(pts_client::executable_in_path('pathcc')) { // PathCC / EKOPath / PathScale Compiler Suite $compilers['pathcc'] = 'PathScale ' . trim(shell_exec('pathcc -dumpversion 2>&1')); } if(pts_client::executable_in_path('tcc')) { // TCC - Tiny C Compiler $tcc = explode(' ', trim(shell_exec('tcc -v 2>&1'))); if($tcc[1] == 'version') { $compilers['opencc'] = 'TCC ' . $tcc[2]; } } if(pts_client::executable_in_path('pcc')) { // PCC - Portable C Compiler $pcc = explode(' ', trim(shell_exec('pcc -version 2>&1'))); if($pcc[0] == 'pcc') { $compilers['pcc'] = 'PCC ' . $pcc[1] . (is_numeric($pcc[2]) ? ' ' . $pcc[2] : null); } } if(pts_client::executable_in_path('pgcpp') || pts_client::executable_in_path('pgCC')) { // The Portland Group Compilers $compilers['pgcpp'] = 'PGI C-C++ Workstation'; } if(pts_client::executable_in_path('clang')) { // Clang $compiler_info = shell_exec('clang --version 2> /dev/null'); if(($cv_pos = stripos($compiler_info, 'clang version')) !== false) { // With Clang 3.0 and prior, the --version produces output where the first line is: // e.g. clang version 3.0 (branches/release_30 142590) $compiler_info = substr($compiler_info, ($cv_pos + 14)); $clang_version = substr($compiler_info, 0, strpos($compiler_info, ' ')); // XXX: the below check bypass now because e.g. Ubuntu appends '-ubuntuX', etc that breaks check if(pts_strings::is_version($clang_version) || true) { // Also see if there is a Clang SVN tag to fetch $compiler_info = substr($compiler_info, 0, strpos($compiler_info, PHP_EOL)); if(($cv_pos = strpos($compiler_info, ')')) !== false) { $compiler_info = substr($compiler_info, 0, $cv_pos); $compiler_info = substr($compiler_info, (strrpos($compiler_info, ' ') + 1)); if(is_numeric($compiler_info)) { // Right now Clang/LLVM uses SVN system and their revisions are only numeric $clang_version .= ' (SVN ' . $compiler_info . ')'; } } $compiler_info = 'Clang ' . $clang_version; } else { $compiler_info = null; } } else { $compiler_info = substr($compiler_info, 0, strpos($compiler_info, PHP_EOL)); } // Clang if(empty($compiler_info) && stripos($compiler_info, 'not found')) { // At least with Clang ~3.0 the -dumpversion is reporting '4.2.1' ratherthan the useful information... // This is likely just for GCC command compatibility, so only use this as a fallback $compiler_info = 'Clang ' . trim(shell_exec('clang -dumpversion 2> /dev/null')); } $compilers['clang'] = $compiler_info; } if(($llvm_ld = pts_client::executable_in_path('llvm-link')) || ($llvm_ld = pts_client::executable_in_path('llvm-ld'))) { // LLVM - Low Level Virtual Machine // Reading the version from llvm-ld (the LLVM linker) should be safe as well for finding out version of LLVM in use // As of LLVM 3.2svn, llvm-ld seems to be llvm-link $info = trim(shell_exec($llvm_ld . ' -version 2> /dev/null')); if(($s = strpos($info, 'version')) != false) { $info = substr($info, 0, strpos($info, PHP_EOL, $s)); $info = substr($info, (strrpos($info, ' ') + 1)); if(pts_strings::is_version(str_replace('svn', null, $info))) { $compilers['llvmc'] = 'LLVM ' . $info; } } } else if(pts_client::executable_in_path('llvm-config')) { // LLVM - Low Level Virtual Machine config $info = trim(shell_exec('llvm-config --version 2> /dev/null')); if(pts_strings::is_version(str_replace('svn', null, $info))) { $compilers['llvmc'] = 'LLVM ' . $info; } } else if(pts_client::executable_in_path('llvmc')) { // LLVM - Low Level Virtual Machine (llvmc) $info = trim(shell_exec('llvmc -version 2>&1')); if(($s = strpos($info, 'version')) != false) { $info = substr($info, 0, strpos($info, "\n", $s)); $info = substr($info, strrpos($info, "\n")); $compilers['llvmc'] = trim($info); } } if(pts_client::executable_in_path('suncc')) { // Sun Studio / SunCC $info = trim(shell_exec('suncc -V 2>&1')); if(($s = strpos($info, 'Sun C')) != false) { $info = substr($info, $s); $info = substr($info, 0, strpos($info, "\n")); $compilers['suncc'] = $info; } } if(pts_client::executable_in_path('ioc')) { // Intel Offline Compiler (IOC) SDK for OpenCL // -v e.g. : Intel(R) SDK for OpenCL* - Offline Compiler 2012 Command-Line Client, version 1.0.2 $info = trim(shell_exec('ioc -version 2>&1')) . ' '; if(($s = strpos($info, 'Offline Compiler ')) != false) { $compilers['ioc'] = 'Intel IOC SDK'; $sv = substr($info, ($s + 17)); $sv = substr($sv, 0, strpos($sv, ' ')); if(is_numeric($sv)) { $compilers['ioc'] .= ' ' . $sv; } if(($s = strpos($info, 'version ')) != false) { $sv = substr($info, ($s + 8)); $sv = substr($sv, 0, strpos($sv, ' ')); if(pts_strings::is_version($sv)) { $compilers['ioc'] .= ' v' . $sv; } } } } if(pts_client::executable_in_path('icc')) { // Intel C++ Compiler $compilers['icc'] = 'ICC'; } if(phodevi::is_macosx() && pts_client::executable_in_path('xcodebuild')) { $xcode = phodevi_osx_parser::read_osx_system_profiler('SPDeveloperToolsDataType', 'Xcode'); $xcode = substr($xcode, 0, strpos($xcode, ' ')); if($xcode) { $compilers['Xcode'] = 'Xcode ' . $xcode; } } if(($nvcc = pts_client::executable_in_path('nvcc')) || is_executable(($nvcc = '/usr/local/cuda/bin/nvcc'))) { // Check outside of PATH too since by default the CUDA Toolkit goes to '/usr/local/cuda/' and relies upon user to update system // NVIDIA CUDA Compiler Driver $nvcc = shell_exec($nvcc . ' --version 2>&1'); if(($s = strpos($nvcc, 'release ')) !== false) { $nvcc = str_replace(array(','), null, substr($nvcc, ($s + 8))); $nvcc = substr($nvcc, 0, strpos($nvcc, ' ')); if(pts_strings::is_version($nvcc)) { $compilers['CUDA'] = 'CUDA ' . $nvcc; } } } // Try to make the compiler that's used by default to appear first if(pts_client::read_env('CC') && isset($compilers[basename(pts_strings::first_in_string(pts_client::read_env('CC'), ' '))])) { $cc_env = basename(pts_strings::first_in_string(pts_client::read_env('CC'), ' ')); $default_compiler = $compilers[$cc_env]; unset($compilers[$cc_env]); array_unshift($compilers, $default_compiler); } else if(pts_client::executable_in_path('cc') && is_link(pts_client::executable_in_path('cc'))) { $cc_link = basename(readlink(pts_client::executable_in_path('cc'))); if(isset($compilers[$cc_link])) { $default_compiler = $compilers[$cc_link]; unset($compilers[pts_client::read_env('CC')]); array_unshift($compilers, $default_compiler); } } return implode(' + ', array_unique($compilers)); } public static function sw_kernel_string() { return phodevi::read_property('system', 'kernel') . ' (' . phodevi::read_property('system', 'kernel-architecture') . ')'; } public static function sw_kernel() { return php_uname('r'); } public static function sw_kernel_parameters() { $parameters = null; if(is_file('/proc/cmdline') && is_file('/proc/modules')) { $modules = array(); foreach(explode(PHP_EOL, pts_file_io::file_get_contents('/proc/modules')) as $module_line) { $module_line = explode(' ', $module_line); if(isset($module_line[0]) && !empty($module_line[0])) { array_push($modules, $module_line[0]); } } if(!empty($modules)) { $to_report = array(); $cmdline = explode(' ', pts_file_io::file_get_contents('/proc/cmdline')); foreach($cmdline as $option) { if(($t = strpos($option, '.')) !== false) { if(in_array(substr($option, 0, $t), $modules)) { array_push($to_report, $option); } } } if(!empty($to_report)) { $parameters = implode(' ', $to_report); } } } return $parameters; } public static function sw_kernel_architecture() { // Find out the kernel archiecture if(phodevi::is_windows()) { //$kernel_arch = strpos($_SERVER['PROCESSOR_ARCHITECTURE'], 64) !== false || strpos($_SERVER['PROCESSOR_ARCHITEW6432'], 64 != false) ? 'x86_64' : 'i686'; $kernel_arch = $_SERVER['PROCESSOR_ARCHITEW6432'] == 'AMD64' ? 'x86_64' : 'i686'; } else { $kernel_arch = php_uname('m'); switch($kernel_arch) { case 'X86-64': case 'amd64': $kernel_arch = 'x86_64'; break; case 'i86pc': case 'i586': case 'i686-AT386': $kernel_arch = 'i686'; break; } } return $kernel_arch; } public static function sw_os_version() { // Returns OS version if(phodevi::is_macosx()) { $os = phodevi_osx_parser::read_osx_system_profiler('SPSoftwareDataType', 'SystemVersion'); $start_pos = strpos($os, '.'); $end_pos = strrpos($os, '.'); $start_pos = strrpos(substr($os, 0, $start_pos), ' '); $end_pos = strpos($os, ' ', $end_pos); $os_version = substr($os, $start_pos + 1, $end_pos - $start_pos); } else if(phodevi::is_linux()) { $os_version = phodevi_linux_parser::read_lsb('Release'); } else { $os_version = php_uname('r'); } return $os_version; } public static function sw_operating_system() { if(!PTS_IS_CLIENT) { // TODO: Figure out why this function is sometimes called from OpenBenchmarking.org.... return false; } // Determine the operating system release if(phodevi::is_linux()) { $vendor = phodevi_linux_parser::read_lsb_distributor_id(); } else if(phodevi::is_hurd()) { $vendor = php_uname('v'); } else { $vendor = null; } $version = phodevi::read_property('system', 'os-version'); if(!$vendor) { $os = null; // Try to detect distro for those not supplying lsb_release $files = pts_file_io::glob('/etc/*-version'); for($i = 0; $i < count($files) && $os == null; $i++) { $file = file_get_contents($files[$i]); if(trim($file) != null) { $os = substr($file, 0, strpos($file, "\n")); } } if($os == null) { $files = pts_file_io::glob('/etc/*-release'); for($i = 0; $i < count($files) && $os == null; $i++) { $file = file_get_contents($files[$i]); if(trim($file) != null) { $proposed_os = substr($file, 0, strpos($file, PHP_EOL)); if(strpos($proposed_os, '=') == false) { $os = $proposed_os; } } else if($i == (count($files) - 1)) { $os = ucwords(substr(($n = basename($files[$i])), 0, strpos($n, '-'))); } } } if($os == null && is_file('/etc/release')) { $file = file_get_contents('/etc/release'); $os = substr($file, 0, strpos($file, "\n")); } if($os == null && is_file('/etc/palm-build-info')) { // Palm / webOS Support $os = phodevi_parser::parse_equal_delimited_file('/etc/palm-build-info', 'PRODUCT_VERSION_STRING'); } if($os == null) { if(phodevi::is_windows()) { $os = trim(exec('ver')); } if(is_file('/etc/debian_version')) { $os = 'Debian ' . php_uname('s') . ' ' . ucwords(pts_file_io::file_get_contents('/etc/debian_version')); } else { $os = php_uname('s'); } } else if(strpos($os, ' ') === false) { // The OS string is only one word, likely a problem... if(is_file('/etc/arch-release') && stripos($os, 'Arch') === false) { // On at least some Arch installs (ARM) the file is empty so would have missed above check $os = trim('Arch Linux ' . $os); } } } else { $os = $vendor . ' ' . $version; } if(($break_point = strpos($os, ':')) > 0) { $os = substr($os, $break_point + 1); } if(phodevi::is_macosx()) { $os = phodevi_osx_parser::read_osx_system_profiler('SPSoftwareDataType', 'SystemVersion'); } if(($break_point = strpos($os, '(')) > 0) { $os = substr($os, 0, $break_point); } $os = trim($os); return $os; } public static function sw_desktop_environment() { $desktop = null; $desktop_environment = null; $desktop_version = null; if(pts_client::is_process_running('gnome-panel')) { // GNOME $desktop_environment = 'GNOME'; if(pts_client::executable_in_path('gnome-about')) { $desktop_version = pts_strings::last_in_string(trim(shell_exec('gnome-about --version 2> /dev/null'))); } else if(pts_client::executable_in_path('gnome-session')) { $desktop_version = pts_strings::last_in_string(trim(shell_exec('gnome-session --version 2> /dev/null'))); } } else if(pts_client::is_process_running('gnome-shell')) { // GNOME 3.0 / GNOME Shell $desktop_environment = 'GNOME Shell'; if(pts_client::executable_in_path('gnome-shell')) { $desktop_version = pts_strings::last_in_string(trim(shell_exec('gnome-shell --version 2> /dev/null'))); } } else if(pts_client::is_process_running('unity-2d-panel')) { // Canonical / Ubuntu Unity 2D Desktop $desktop_environment = 'Unity 2D'; if(pts_client::executable_in_path('unity')) { $desktop_version = pts_strings::last_in_string(trim(shell_exec('unity --version 2> /dev/null'))); } } else if(pts_client::is_process_running('unity-panel-service')) { // Canonical / Ubuntu Unity Desktop $desktop_environment = 'Unity'; if(pts_client::executable_in_path('unity')) { $desktop_version = pts_strings::last_in_string(trim(shell_exec('unity --version 2> /dev/null'))); } } else if(($kde4 = pts_client::is_process_running('kded4')) || pts_client::is_process_running('kded')) { // KDE 4.x $desktop_environment = 'KDE'; $kde_output = trim(shell_exec(($kde4 ? 'kde4-config' : 'kde-config') . ' --version 2>&1')); $kde_lines = explode("\n", $kde_output); for($i = 0; $i < count($kde_lines) && empty($desktop_version); $i++) { $line_segments = pts_strings::colon_explode($kde_lines[$i]); if(in_array($line_segments[0], array('KDE', 'KDE Development Platform')) && isset($line_segments[1])) { $v = trim($line_segments[1]); if(($cut = strpos($v, ' ')) > 0) { $v = substr($v, 0, $cut); } $desktop_version = $v; } } } else if(pts_client::is_process_running('chromeos-wm')) { $chrome_output = trim(shell_exec('chromeos-wm -version')); if($chrome_output == 'chromeos-wm') { // No version actually reported $chrome_output = 'Chrome OS'; } $desktop_environment = $chrome_output; } else if(pts_client::is_process_running('lxsession')) { $lx_output = trim(shell_exec('lxpanel --version')); $version = substr($lx_output, strpos($lx_output, ' ') + 1); $desktop_environment = 'LXDE'; $desktop_version = $version; } else if(pts_client::is_process_running('xfce4-session') || pts_client::is_process_running('xfce-mcs-manager')) { // Xfce 4.x $desktop_environment = 'Xfce'; $xfce_output = trim(shell_exec('xfce4-session-settings --version 2>&1')); if(($open = strpos($xfce_output, '(Xfce')) > 0) { $xfce_output = substr($xfce_output, strpos($xfce_output, ' ', $open) + 1); $desktop_version = substr($xfce_output, 0, strpos($xfce_output, ')')); } } else if(pts_client::is_process_running('sugar-session')) { // Sugar Desktop Environment (namely for OLPC) $desktop_environment = 'Sugar'; $desktop_version = null; // TODO: where can the Sugar version be figured out? } else if(pts_client::is_process_running('openbox')) { $desktop_environment = 'Openbox'; $openbox_output = trim(shell_exec('openbox --version 2>&1')); if(($openbox_d = stripos($openbox_output, 'Openbox ')) !== false) { $openbox_output = substr($openbox_output, ($openbox_d + 8)); $desktop_version = substr($openbox_output, 0, strpos($openbox_output, PHP_EOL)); } } else if(pts_client::is_process_running('cinnamon')) { $desktop_environment = 'Cinnamon'; $desktop_version = pts_strings::last_in_string(trim(shell_exec('cinnamon --version 2> /dev/null'))); } else if(pts_client::is_process_running('enlightenment')) { $desktop_environment = 'Enlightenment'; $desktop_version = null; // No known -v / --version command on any Enlightenment component } else if(pts_client::is_process_running('consort-panel')) { $desktop_environment = 'Consort'; $desktop_version = null; // TODO: Haven't tested Consort Desktop yet } else if(pts_client::is_process_running('razor-desktop')) { $desktop_environment = 'Razor-qt'; $desktop_version = null; // TODO: Figure out how to determine razor version } else if(pts_client::is_process_running('icewm')) { $desktop_environment = 'IceWM'; $desktop_version = null; } if(!empty($desktop_environment)) { $desktop = $desktop_environment; if(!empty($desktop_version) && pts_strings::is_version($desktop_version)) { $desktop .= ' ' . $desktop_version; } } return $desktop; } public static function sw_display_server() { $info = null; if(phodevi::is_windows()) { // TODO: determine what to do for Windows support $info = false; } else { if(($x_bin = pts_client::executable_in_path('Xorg')) || ($x_bin = pts_client::executable_in_path('X'))) { // Find graphics subsystem version $info = shell_exec($x_bin . ' ' . (phodevi::is_solaris() ? ':0' : '') . ' -version 2>&1'); $pos = (($p = strrpos($info, 'Release Date')) !== false ? $p : strrpos($info, 'Build Date')); $info = trim(substr($info, 0, $pos)); if($pos === false || getenv('DISPLAY') == false) { $info = null; } else if(($pos = strrpos($info, '(')) === false) { $info = trim(substr($info, strrpos($info, ' '))); } else { $info = trim(substr($info, strrpos($info, 'Server') + 6)); } if($info != null) { $info = 'X Server ' . $info; } } else if(pts_client::is_process_running('surfaceflinger')) { $info = 'SurfaceFlinger'; } if(pts_client::is_process_running('unity-system-compositor')) { $unity_system_comp = trim(str_replace('unity-system-compositor', null, shell_exec('unity-system-compositor --version 2>&1'))); if(pts_strings::is_version($unity_system_comp)) { $info = 'Unity-System-Compositor ' . $unity_system_comp . ($info != null ? ' + ' . $info : null); } } } return $info; } public static function sw_display_driver($with_version = true) { if(phodevi::is_windows()) { return null; } $display_driver = phodevi::read_property('system', 'dri-display-driver'); if(empty($display_driver)) { if(phodevi::is_ati_graphics() && phodevi::is_linux()) { $display_driver = 'fglrx'; } else if(phodevi::is_nvidia_graphics()) { $display_driver = 'nvidia'; } else if((phodevi::is_mesa_graphics() || phodevi::is_bsd()) && stripos(phodevi::read_property('gpu', 'model'), 'NVIDIA') !== false) { if(is_file('/sys/class/drm/version')) { // If there's DRM loaded and NVIDIA, it should be Nouveau $display_driver = 'nouveau'; } else { // The dead xf86-video-nv doesn't use any DRM $display_driver = 'nv'; } } else { // Fallback to hopefully detect the module, takes the first word off the GPU string and sees if it is the module // This works in at least the case of the Cirrus driver $display_driver = strtolower(pts_strings::first_in_string(phodevi::read_property('gpu', 'model'))); } } if(!empty($display_driver)) { $driver_version = phodevi_parser::read_xorg_module_version($display_driver . '_drv'); if($driver_version == false || $driver_version == '1.0.0') { switch($display_driver) { case 'amd': // See if it's radeon driver $driver_version = phodevi_parser::read_xorg_module_version('radeon_drv'); if($driver_version != false) { $display_driver = 'radeon'; } break; case 'vmwgfx': // See if it's VMware driver $driver_version = phodevi_parser::read_xorg_module_version('vmware_drv'); if($driver_version != false) { $display_driver = 'vmware'; } break; case 'radeon': // RadeonHD driver also reports DRI driver as 'radeon', so try reading that instead $driver_version = phodevi_parser::read_xorg_module_version('radeonhd_drv'); if($driver_version != false) { $display_driver = 'radeonhd'; } break; case 'nvidia': case 'NVIDIA': // NVIDIA's binary driver usually ends up reporting 1.0.0 if(($nvs_value = phodevi_parser::read_nvidia_extension('NvidiaDriverVersion'))) { $driver_version = $nvs_value; } else { // NVIDIA's binary driver appends their driver version on the end of the OpenGL version string $glxinfo = phodevi_parser::software_glxinfo_version(); if(($pos = strpos($glxinfo, 'NVIDIA ')) != false) { $driver_version = substr($glxinfo, ($pos + 7)); } } break; default: if(is_readable('/sys/class/graphics/fb0/name')) { // This path works for at least finding NVIDIA Tegra 2 DDX (via tegra_fb) $display_driver = file_get_contents('/sys/class/graphics/fb0/name'); $display_driver = str_replace(array('drm', '_fb'), null, $display_driver); $driver_version = phodevi_parser::read_xorg_module_version($display_driver . '_drv'); } break; } } if($driver_version == false) { // If the version is empty, chances are the DDX driver string is incorrect $display_driver = null; // See if the VESA or fbdev driver is in use foreach(array('modesetting', 'fbdev', 'vesa') as $drv) { $drv_version = phodevi_parser::read_xorg_module_version($drv . '_drv'); if($drv_version) { $display_driver = $drv; $driver_version = $drv_version; break; } } } if(!empty($driver_version) && $with_version && $driver_version != '0.0.0') { $display_driver .= ' ' . $driver_version; // XXX: The below check is disabled since the Catalyst Version no longer seems reliably reported (circa Catalyst 13.x) if(false && phodevi::is_ati_graphics() && strpos($display_driver, 'fglrx') !== false) { $catalyst_version = phodevi_linux_parser::read_amd_pcsdb('AMDPCSROOT/SYSTEM/LDC,Catalyst_Version'); if($catalyst_version != null && $catalyst_version > 10.1 && $catalyst_version != 10.5 && $catalyst_version != 11.8) { // This option was introduced around Catalyst 10.5 but seems to not be updated properly until Catalyst 10.11/10.12 $display_driver .= ' Catalyst ' . $catalyst_version . ''; } } } } return $display_driver; } public static function sw_opengl_driver() { // OpenGL version $info = null; if(phodevi::is_windows()) { $info = null; // TODO: Windows support } else if(pts_client::executable_in_path('nvidia-settings')) { $info = phodevi_parser::read_nvidia_extension('OpenGLVersion'); } if($info == null) { $info = phodevi_parser::software_glxinfo_version(); if($info && ($pos = strpos($info, ' ')) != false && strpos($info, 'Mesa') === false) { $info = substr($info, 0, $pos); } $renderer = phodevi_parser::read_glx_renderer(); if($renderer && ($s = strpos($renderer, 'Gallium')) !== false) { $renderer = substr($renderer, $s); $renderer = substr($renderer, 0, strpos($renderer, ' ', strpos($renderer, '.'))); $info .= ' ' . $renderer . ''; } } return $info; } public static function sw_opengl_vendor() { // OpenGL version $info = null; if(pts_client::executable_in_path('glxinfo')) { $info = shell_exec('glxinfo 2>&1 | grep vendor'); if(($pos = strpos($info, 'OpenGL vendor string:')) !== false) { $info = substr($info, $pos + 22); $info = trim(substr($info, 0, strpos($info, "\n"))); } } else if(is_readable('/dev/nvidia0')) { $info = 'NVIDIA'; } else if(is_readable('/sys/module/fglrx/initstate') && pts_file_io::file_get_contents('/sys/module/fglrx/initstate') == 'live') { $info = 'ATI'; } else if(is_readable('/dev/dri/card0')) { $info = 'Mesa'; } else if(phodevi::is_bsd() && phodevi_bsd_parser::read_sysctl('dev.nvidia.0.%driver')) { $info = 'NVIDIA'; } return $info; } public static function sw_compiler_build_configuration($compiler) { $cc = shell_exec($compiler . ' -v 2>&1'); if(($t = stripos($cc, 'Configured with: ')) !== false) { $cc = substr($cc, ($t + 18)); $cc = substr($cc, 0, strpos($cc, PHP_EOL)); $cc = explode(' ', $cc); array_shift($cc); // this should just be the configure call (i.e. ../src/configure) $drop_arguments = array( '--with-pkgversion=', '--with-bugurl=', '--prefix=', '--program-suffix=', '--libexecdir=', '--infodir=', '--libdir=', '--with-sysroot=', '--with-gxx-include-dir=', '--with-system-zlib', '--enable-linker-build-id', '--without-included-gettext' ); foreach($cc as $i => $argument) { $arg_length = strlen($argument); if($argument[0] != '-') { unset($cc[$i]); } else { foreach($drop_arguments as $check_to_drop) { $len = strlen($check_to_drop); if($len <= $arg_length && substr($argument, 0, $len) == $check_to_drop) { unset($cc[$i]); } } } } sort($cc); $cc = implode(' ', $cc); } else if(($t = stripos($cc, 'clang')) !== false) { $cc = null; // Clang doesn't report "configured with" but has other useful tid-bits... if(($c = pts_client::executable_in_path('llvm-ld')) || ($c = pts_client::executable_in_path('llvm-link'))) { $llvm_ld = shell_exec($c . ' -version 2>&1'); /* EXAMPLE OUTPUT: LLVM (http://llvm.org/): LLVM version 3.1svn Optimized build. Built Mar 23 2012 (08:53:34). Default target: x86_64-unknown-linux-gnu Host CPU: corei7-avx */ if(stripos($llvm_ld, 'build') && (stripos($llvm_ld, 'host') || stripos($llvm_ld, 'target'))) { $llvm_ld = explode(PHP_EOL, $llvm_ld); if(stripos($llvm_ld[0], 'http://')) { array_shift($llvm_ld); } if(stripos($llvm_ld[0], 'version')) { array_shift($llvm_ld); } foreach($llvm_ld as $i => &$line) { $line = trim($line); if(substr($line, -1) == '.') { $line = substr($line, 0, -1); } if($line == null) { unset($llvm_ld[$i]); } } $cc = implode('; ', $llvm_ld); } } } else { $cc = null; } return $cc; } public static function sw_dri_display_driver() { $dri_driver = false; if(is_file('/proc/dri/0/name')) { $driver_info = file_get_contents('/proc/dri/0/name'); $dri_driver = substr($driver_info, 0, strpos($driver_info, ' ')); if(in_array($dri_driver, array('i915', 'i965'))) { $dri_driver = 'intel'; } } else if(is_file('/sys/class/drm/card0/device/vendor')) { $vendor_id = file_get_contents('/sys/class/drm/card0/device/vendor'); switch($vendor_id) { case 0x1002: $dri_driver = 'radeon'; break; case 0x8086: $dri_driver = 'intel'; break; case 0x10de: // NVIDIA $dri_driver = 'nouveau'; break; } } return $dri_driver; } public static function sw_java_version() { $java_version = trim(shell_exec('java -version 2>&1')); if(strpos($java_version, 'not found') == false && strpos($java_version, 'Java') !== FALSE) { $java_version = explode("\n", $java_version); if(($cut = count($java_version) - 2) > 0) { $v = $java_version[$cut]; } else { $v = array_pop($java_version); } $java_version = trim($v); } else { $java_version = null; } return $java_version; } public static function sw_python_version() { $python_version = null; if(pts_client::executable_in_path('python') != false) { $python_version = trim(shell_exec('python -V 2>&1')); } return $python_version; } public static function sw_wine_version() { $wine_version = null; if(pts_client::executable_in_path('wine') != false) { $wine_version = trim(shell_exec('wine --version 2>&1')); } else if(pts_client::executable_in_path('winecfg.exe') != false && pts_client::read_env('WINE_VERSION')) { $wine_version = trim(pts_client::read_env('WINE_VERSION')); if(stripos($wine_version, 'wine') === false) { $wine_version = 'wine-' . $wine_version; } } return $wine_version; } } ?> phoronix-test-suite/pts-core/objects/phodevi/components/phodevi_memory.php0000644000175000017500000002132612167103320027364 0ustar michaelmichael. */ class phodevi_memory extends phodevi_device_interface { public static function read_property($identifier) { switch($identifier) { case 'identifier': $property = new phodevi_device_property('memory_string', phodevi::smart_caching); break; case 'capacity': $property = new phodevi_device_property('memory_capacity', phodevi::smart_caching); break; } return $property; } public static function memory_string() { $mem_string = null; $mem_prefix = null; $mem_size = false; $mem_speed = false; $mem_type = false; $mem_manufacturer = false; $mem_part = false; if(phodevi::is_macosx()) { $mem_size = phodevi_osx_parser::read_osx_system_profiler('SPMemoryDataType', 'Size', true, array('Empty')); $mem_speed = phodevi_osx_parser::read_osx_system_profiler('SPMemoryDataType', 'Speed'); $mem_type = phodevi_osx_parser::read_osx_system_profiler('SPMemoryDataType', 'Type'); } else if(phodevi::is_solaris()) { $mem_size = phodevi_solaris_parser::read_sun_ddu_dmi_info('MemoryDevice*,InstalledSize'); $mem_speed = phodevi_solaris_parser::read_sun_ddu_dmi_info('MemoryDevice*,Speed'); $mem_type = phodevi_solaris_parser::read_sun_ddu_dmi_info('MemoryDevice*,MemoryDeviceType'); if(is_array($mem_speed) && count($mem_speed) > 0) { $mem_speed = array_shift($mem_speed); } $mem_speed = str_replace('MHZ', 'MHz', $mem_speed); } else if(phodevi::is_windows()) { $mem_size = phodevi_windows_parser::read_cpuz('DIMM #', 'Size', true); foreach($mem_size as $key => &$individual_size) { $individual_size = pts_arrays::first_element(explode(' ', $individual_size)); if(!is_numeric($individual_size)) { unset($mem_size[$key]); } } $mem_type = phodevi_windows_parser::read_cpuz('Memory Type', null); $mem_speed = intval(phodevi_windows_parser::read_cpuz('Memory Frequency', null)) . 'MHz'; } else if(phodevi::is_linux()) { $mem_size = phodevi_linux_parser::read_dmidecode('memory', 'Memory Device', 'Size', false, array('Not Installed', 'No Module Installed')); $mem_speed = phodevi_linux_parser::read_dmidecode('memory', 'Memory Device', 'Speed', true, 'Unknown'); $mem_type = phodevi_linux_parser::read_dmidecode('memory', 'Memory Device', 'Type', true, array('Unknown', 'Other', 'Flash')); $mem_manufacturer = phodevi_linux_parser::read_dmidecode('memory', 'Memory Device', 'Manufacturer', true, array('Unknown')); $mem_part = phodevi_linux_parser::read_dmidecode('memory', 'Memory Device', 'Part Number', true, array('Unknown')); } if(is_array($mem_type)) { $mem_type = array_pop($mem_type); } if($mem_size != false && (!is_array($mem_size) || count($mem_size) != 0)) { for($i = 0; $i < count($mem_size); $i++) { switch(substr($mem_size[$i], -1)) { case 'K': // looks like sometimes Solaris now reports flash chip as memory. its string ends with K unset($mem_size[$i]); unset($mem_speed[$i]); unset($mem_type[$i]); break; case 'M': // report megabytes as MB, just not M, as on Solaris $mem_size[$i] .= 'B'; break; case 'B': if(strtolower(substr($mem_size[$i], -2, 1)) == 'k') { // some hardware on Linux via dmidecode reports flash chips unset($mem_size[$i]); //unset($mem_speed[$i]); //unset($mem_type[$i]); } break; } } foreach($mem_size as $i => $mem_stick) { if(!is_numeric(substr($mem_stick, 0, 3)) && stripos($mem_stick, 'GB') == false) { // If the memory size isn't at least three digits (basically 128MB+), chances are something is wrong, i.e. reporting flash chip from dmidecode, so get rid of it. unset($mem_size[$i]); } } $mem_count = count($mem_size); if(!empty($mem_type)) { if(($cut = strpos($mem_type, ' ')) > 0) { $mem_type = substr($mem_type, 0, $cut); } if(!in_array($mem_type, array('Other')) && (pts_strings::keep_in_string($mem_type, pts_strings::CHAR_NUMERIC | pts_strings::CHAR_LETTER) == $mem_type || phodevi::is_windows())) { $mem_prefix = $mem_type; } } else { $mem_prefix = null; } if(!empty($mem_speed)) { if(($cut = strpos($mem_speed, ' (')) > 0) { $mem_speed = substr($mem_speed, 0, $cut); } if(!empty($mem_prefix)) { $mem_prefix .= '-'; } $mem_prefix .= str_replace(' ', null, $mem_speed); } // TODO: Allow a combination of both functions below, so like 2 x 2GB + 3 x 1GB DDR2-800 if($mem_count > 1 && count(array_unique($mem_size)) > 1) { $mem_string = implode(' + ', $mem_size) . ' ' . $mem_prefix; } else { if(($mem_count * $mem_size[0]) != phodevi::read_property('memory', 'capacity') && phodevi::read_property('memory', 'capacity') % $mem_size[0] == 0) { // This makes sure the correct number of RAM modules is reported... // On at least Linux with dmidecode on an AMD Opteron multi-socket setup it's only showing the data for one socket if($mem_size[0] < 1024) { $mem_size[0] *= 1024; } $mem_count = phodevi::read_property('memory', 'capacity') / $mem_size[0]; } $product_string = null; if(isset($mem_manufacturer[2]) && ctype_alpha($mem_manufacturer[0]) && stripos($mem_manufacturer, 'manufacturer') === false && stripos($mem_manufacturer, 'part') === false && stripos($mem_manufacturer, 'module') === false && stripos($mem_manufacturer, 'dimm') === false && isset($mem_manufacturer[2]) && ctype_alpha($mem_manufacturer)) { $product_string .= ' ' . $mem_manufacturer; } if(isset($mem_part[2]) && stripos($mem_part, 'part') === false && stripos($mem_part, 'module') === false && stripos($mem_part, 'dimm') === false && substr($mem_part, 0, 2) != '0x' && !isset($mem_part[24]) && ctype_alnum($mem_part)) { $product_string .= ' ' . $mem_part; } if(is_numeric($mem_size[0]) && stripos($mem_size[0], 'b') === false) { if($mem_size >= 1024) { $mem_size[0] .= ' MB'; } else { $mem_size[0] .= ' GB'; } } $mem_string = $mem_count . ' x ' . $mem_size[0] . ' ' . $mem_prefix . $product_string; } } if(empty($mem_string)) { $mem_string = phodevi::read_property('memory', 'capacity'); if($mem_string != null) { $mem_string .= 'MB'; } } return trim($mem_string); } public static function memory_capacity() { // Returns physical memory capacity if(isset(phodevi::$vfs->meminfo)) { $info = phodevi::$vfs->meminfo; $info = substr($info, strpos($info, 'MemTotal:') + 9); $info = intval(trim(substr($info, 0, strpos($info, 'kB')))); $info = floor($info / 1024); if(is_numeric($info) && $info > 950) { if($info > 4608) { $info = ceil($info / 1024) * 1024; } else if($info > 1536) { $info = ceil($info / 512) * 512; } else { $info = ceil($info / 256) * 256; } } } else if(phodevi::is_solaris()) { $info = shell_exec('prtconf 2>&1 | grep Memory'); $info = substr($info, strpos($info, ':') + 2); $info = substr($info, 0, strpos($info, 'Megabytes')); } else if(phodevi::is_bsd()) { $mem_size = phodevi_bsd_parser::read_sysctl('hw.physmem'); if($mem_size == false) { $mem_size = phodevi_bsd_parser::read_sysctl('hw.realmem'); } $info = ceil(floor($mem_size / 1048576) / 256) * 256; } else if(phodevi::is_macosx()) { $info = phodevi_osx_parser::read_osx_system_profiler('SPHardwareDataType', 'Memory'); $info = explode(' ', $info); $info = (isset($info[1]) && $info[1] == 'GB' ? $info[0] * 1024 : $info[0]); } else if(phodevi::is_windows()) { $info = phodevi_windows_parser::read_cpuz('Memory Size', null); if($info != null) { if(($e = strpos($info, ' MBytes')) !== false) { $info = substr($info, 0, $e); } $info = trim($info); } } else { $info = null; } return $info; } } ?> phoronix-test-suite/pts-core/objects/phodevi/components/phodevi_cpu.php0000644000175000017500000003712512167105672026663 0ustar michaelmichael. */ class phodevi_cpu extends phodevi_device_interface { // TODO XXX: $cpuinfo is now useless and needs to be replaced by the VFS layer... update OpenBenchmarking.org accordingly public static $cpuinfo = false; private static $cpu_flags = -1; public static function read_property($identifier) { switch($identifier) { case 'identifier': $property = new phodevi_device_property('cpu_string', phodevi::smart_caching); break; case 'model': $property = new phodevi_device_property('cpu_model', phodevi::smart_caching); break; case 'mhz-default-frequency': $property = new phodevi_device_property('cpu_default_frequency_mhz', phodevi::smart_caching); break; case 'default-frequency': $property = new phodevi_device_property(array('cpu_default_frequency', 0), phodevi::smart_caching); break; case 'core-count': $property = new phodevi_device_property('cpu_core_count', phodevi::smart_caching); break; case 'scaling-governor': $property = new phodevi_device_property('cpu_scaling_governor', phodevi::std_caching); break; } return $property; } public static function cpu_string() { $model = phodevi::read_property('cpu', 'model'); // Append the processor frequency to string if(($freq = phodevi::read_property('cpu', 'default-frequency')) > 0) { $model = str_replace($freq . 'GHz', null, $model); // we'll replace it if it's already in the string $model .= ' @ ' . $freq . 'GHz'; } $core_count = phodevi::read_property('cpu', 'core-count'); return $model . ' (' . $core_count . ' Core' . ($core_count > 1 ? 's' : null) . ')'; } public static function cpu_core_count() { $info = null; if(getenv('NUMBER_OF_PROCESSORS') && is_numeric(getenv('NUMBER_OF_PROCESSORS'))) { // Should be used by Windows they have NUMBER_OF_PROCESSORS set and use this as an easy way to override CPUs exposed $info = getenv('NUMBER_OF_PROCESSORS'); } else if(phodevi::is_linux()) { if(is_file('/sys/devices/system/cpu/online')) { $present = pts_file_io::file_get_contents('/sys/devices/system/cpu/online'); if(isset($present[2]) && substr($present, 0, 2) == '0-') { $present = substr($present, 2); if(is_numeric($present)) { $info = $present + 1; } } } } else if(phodevi::is_solaris()) { $info = count(explode(PHP_EOL, trim(shell_exec('psrinfo')))); } else if(phodevi::is_bsd()) { $info = intval(phodevi_bsd_parser::read_sysctl(array('hw.ncpufound', 'hw.ncpu'))); } else if(phodevi::is_macosx()) { $info = phodevi_osx_parser::read_osx_system_profiler('SPHardwareDataType', 'TotalNumberOfCores'); } else if(phodevi::is_windows()) { // Should be hit by the first NUMBER_OF_PROCESSORS env check... //$info = getenv('NUMBER_OF_PROCESSORS'); } if($info == null && isset(phodevi::$vfs->cpuinfo)) { $info = self::cpuinfo_core_count(); } return (is_numeric($info) && $info > 0 ? $info : 1); } public static function cpu_default_frequency_mhz() { return self::cpu_default_frequency() * 1000; } public static function cpu_scaling_governor() { $scaling_governor = false; if(is_file('/sys/devices/system/cpu/cpu0/cpufreq/scaling_driver')) { $scaling_governor = pts_file_io::file_get_contents('/sys/devices/system/cpu/cpu0/cpufreq/scaling_driver') . ' '; } if(is_file('/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor')) { $scaling_governor .= pts_file_io::file_get_contents('/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor'); } return trim($scaling_governor); } public static function is_genuine($cpu) { /* Real/Genuine CPUs should have: 1. Contain more than one word in string 2. Check vendor (to avoid QEMU, Virtual CPU, etc): Intel, VIA, AMD, ARM, SPARC */ return strpos($cpu, ' ') !== false && strpos($cpu, ' ') != strrpos($cpu, ' ') && pts_strings::has_in_istring($cpu, array('Intel', 'VIA', 'AMD', 'ARM', 'SPARC', 'Transmeta')) && stripos($cpu, 'unknown') === false; } public static function cpu_default_frequency($cpu_core = 0) { // Find out the processor frequency $info = null; // 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_max_freq')) { $info = pts_file_io::file_get_contents('/sys/devices/system/cpu/cpu' . $cpu_core . '/cpufreq/scaling_max_freq'); $info = intval($info) / 1000000; if($info > 9) { // For some reason on Linux 3.10 the scaling_max_freq is reported as 25GHz... $info = null; } } if($info == null && isset(phodevi::$vfs->cpuinfo)) // fall back for those without cpufreq { $cpu_mhz = self::read_cpuinfo_line('cpu MHz'); $info = $cpu_mhz / 1000; } else if($info == null && phodevi::is_bsd()) { $info = phodevi_bsd_parser::read_sysctl(array('dev.cpu.0.freq_levels')); if($info != null) { // Popping the top speed off of dev.cpu.0.freq_levels should be the default/highest supported frequency $info = pts_arrays::first_element(explode(' ', str_replace('/', ' ', $info))); if(!is_numeric($info)) { $info = null; } } if($info == null) { $info = phodevi_bsd_parser::read_sysctl(array('hw.acpi.cpu.px_global', 'machdep.est.frequency.target', 'hw.cpuspeed')); } if($info == null) { // dev.cpu.0.freq seems to be the real/current frequency, affected by power management, etc so only use as last fallback $info = phodevi_bsd_parser::read_sysctl(array('dev.cpu.0.freq')); } if(is_numeric($info)) { $info = $info / 1000; } else { $info = null; } } else if($info == null && phodevi::is_windows()) { $info = phodevi_windows_parser::read_cpuz('Processor 1', 'Stock frequency'); if($info != null) { if(($e = strpos($info, ' MHz')) !== false) { $info = substr($info, 0, $e); } $info = $info / 1000; } } else if($info == null) { $info = phodevi::read_sensor(array('cpu', 'freq')); if($info > 1000) { // Convert from MHz to GHz $info = $info / 1000; } } return pts_math::set_precision($info, 2); } public static function cpu_model() { // Returns the processor name / frequency information $info = null; if(isset(phodevi::$vfs->cpuinfo)) { $physical_cpu_ids = phodevi_linux_parser::read_cpuinfo('physical id'); $physical_cpu_count = count(array_unique($physical_cpu_ids)); $cpu_strings = phodevi_linux_parser::read_cpuinfo(array('model name', 'Processor')); $cpu_strings_unique = array_unique($cpu_strings); if($physical_cpu_count == 1 || empty($physical_cpu_count)) { // Just one processor if(($cut = strpos($cpu_strings[0], ' (')) !== false) { $cpu_strings[0] = substr($cpu_strings[0], 0, $cut); } $info = $cpu_strings[0]; if(strpos($info, 'ARM') !== false) { if(is_dir('/sys/devices/system/exynos-core/') && stripos($info, 'Exynos') === false) { $info = 'Exynos ' . $info; } } } else if($physical_cpu_count > 1 && count($cpu_strings_unique) == 1) { // Multiple processors, same model $info = $physical_cpu_count . ' x ' . $cpu_strings[0]; } else if($physical_cpu_count > 1 && count($cpu_strings_unique) > 1) { // Multiple processors, different models $current_id = -1; $current_string = $cpu_strings[0]; $current_count = 0; $cpus = array(); for($i = 0; $i < count($physical_cpu_ids); $i++) { if($current_string != $cpu_strings[$i] || $i == (count($physical_cpu_ids) - 1)) { array_push($cpus, $current_count . ' x ' . $current_string); $current_string = $cpu_strings[$i]; $current_count = 0; } if($physical_cpu_ids[$i] != $current_id) { $current_count++; $current_id = $physical_cpu_ids[$i]; } } $info = implode(', ', $cpus); } } else if(phodevi::is_solaris()) { $dmi_cpu = phodevi_solaris_parser::read_sun_ddu_dmi_info('CPUType', '-C'); if(count($dmi_cpu) == 0) { $dmi_cpu = phodevi_solaris_parser::read_sun_ddu_dmi_info('ProcessorName'); } if(count($dmi_cpu) > 0) { $info = $dmi_cpu[0]; } else { $info = trim(shell_exec('dmesg 2>&1 | grep cpu0')); $info = trim(substr($info, strrpos($info, 'cpu0:') + 6)); if(empty($info)) { $info = array_pop(phodevi_solaris_parser::read_sun_ddu_dmi_info('ProcessorManufacturer')); } } //TODO: Add in proper support for reading multiple CPUs, similar to the code from above $physical_cpu_count = count(phodevi_solaris_parser::read_sun_ddu_dmi_info('ProcessorSocketType')); if($physical_cpu_count > 1 && !empty($info)) { // TODO: For now assuming when multiple CPUs are installed, that they are of the same type $info = $physical_cpu_count . ' x ' . $info; } } else if(phodevi::is_bsd()) { $info = phodevi_bsd_parser::read_sysctl('hw.model'); } else if(phodevi::is_macosx()) { $info = phodevi_osx_parser::read_osx_system_profiler('SPHardwareDataType', 'ProcessorName'); } else if(phodevi::is_windows()) { $info = phodevi_windows_parser::read_cpuz('Processor 1', 'Name'); if(!$info) { $info = getenv('PROCESSOR_IDENTIFIER'); } } if(empty($info)) { $info = 'Unknown'; } else { if(($strip_point = strpos($info, '@')) > 0) { $info = trim(substr($info, 0, $strip_point)); // stripping out the reported freq, since the CPU could be overclocked, etc } $info = pts_strings::strip_string($info); // It seems Intel doesn't report its name when reporting Pentium hardware if(strpos($info, 'Pentium') !== false && strpos($info, 'Intel') === false) { $info = 'Intel ' . $info; } if(substr($info, 0, 5) == 'Intel') { $cpu_words = explode(' ', $info); $cpu_words_count = count($cpu_words); // Convert strings like 'Intel Core i7 M 620' -> 'Intel Core i7 620M' and 'Intel Core i7 X 990' -> 'Intel Core i7 990X' to better reflect Intel product marketing names if($cpu_words_count > 4 && is_numeric($cpu_words[($cpu_words_count - 1)]) && strlen($cpu_words[($cpu_words_count - 2)]) == 1 && strlen($cpu_words[($cpu_words_count - 3)]) == 2) { $cpu_words[($cpu_words_count - 1)] .= $cpu_words[($cpu_words_count - 2)]; unset($cpu_words[($cpu_words_count - 2)]); $info = implode(' ', $cpu_words); } } } return $info; } public static function get_cpu_feature_constants() { return array( 'sse2' => (1 << 1), // SSE 2 'sse3' => (1 << 2), // SSE 3 'sse4a' => (1 << 3), // SSE 4a 'sse4_1' => (1 << 4), // SSE 4.1 'sse4_2' => (1 << 5), // SSE 4.2 'sse5' => (1 << 6), // SSE 5 'avx' => (1 << 7), // AVX 'avx2' => (1 << 8), // AVX2 'aes' => (1 << 9), // AES 'epb' => (1 << 10), // EPB 'svm' => (1 << 11), // AMD SVM (Virtualization) 'vmx' => (1 << 12), // Intel Virtualization 'xop' => (1 << 13), // AMD XOP Instruction Set 'fma3' => (1 << 14), // FMA3 Instruction Set 'fma4' => (1 << 15), // FMA4 Instruction Set 'rdrand' => (1 << 16), // Intel Bull Mountain RDRAND - Ivy Bridge 'fsgsbase' => (1 << 17), // FSGSBASE - Ivy Bridge AVX 'bmi2' => (1 << 18) // Intel Haswell has BMI2 ); } public static function get_cpu_feature_constant($constant) { $features = self::get_cpu_feature_constants(); return isset($features[$constant]) ? $features[$constant] : -1; } public static function read_cpuinfo_line($key, $from_start = true) { $line = false; $key .= "\t"; if(isset(phodevi::$vfs->cpuinfo) && ($from_start && ($key_pos = strpos(phodevi::$vfs->cpuinfo, PHP_EOL . $key)) !== false) || ($key_pos = strrpos(phodevi::$vfs->cpuinfo, PHP_EOL . $key)) !== false) { $line = substr(phodevi::$vfs->cpuinfo, $key_pos); $line = substr($line, strpos($line, ':') + 1); $line = trim(substr($line, 0, strpos($line, PHP_EOL))); } return $line; } public static function set_cpu_feature_flags() { $flags = explode(' ', self::read_cpuinfo_line('flags')); self::$cpu_flags = 0; foreach(self::get_cpu_feature_constants() as $feature => $value) { if(in_array($feature, $flags)) { // The feature is supported on the CPU self::$cpu_flags |= $value; } } } public static function get_cpu_flags() { if(self::$cpu_flags === -1) { self::set_cpu_feature_flags(); } return self::$cpu_flags; } public static function instruction_set_extensions() { $constants = self::get_cpu_feature_constants(); self::set_cpu_feature_flags(); $cpu_flags = self::get_cpu_flags(); $extension_string = null; foreach($constants as $feature => $value) { // find maximum SSE version if(substr($feature, 0, 3) == 'sse' && ($cpu_flags & $value)) { $extension_string = 'SSE ' . str_replace('_', '.', substr($feature, 3)); } } // Check for other instruction sets foreach(array('avx2', 'avx', 'xop', 'fma3', 'fma4', 'rdrand', 'fsgsbase') as $instruction_set) { if(($cpu_flags & self::get_cpu_feature_constant($instruction_set))) { $extension_string .= ($extension_string != null ? ' + ' : null) . strtoupper($instruction_set); } } return $extension_string; } public static function virtualization_technology() { $constants = self::get_cpu_feature_constants(); $cpu_flags = self::get_cpu_flags(); $virtualitzation_technology = false; if(($cpu_flags & self::get_cpu_feature_constant('vmx'))) { $virtualitzation_technology = 'VT-x'; } else if(($cpu_flags & self::get_cpu_feature_constant('svm'))) { $virtualitzation_technology = 'AMD-V'; } return $virtualitzation_technology; } public static function lscpu_l2_cache() { $l2_cache = false; if(isset(phodevi::$vfs->lscpu) && ($t = strpos(phodevi::$vfs->lscpu, 'L2 cache:'))) { $lscpu = substr(phodevi::$vfs->lscpu, $t + strlen('L2 cache:') + 1); $lscpu = substr($lscpu, 0, strpos($lscpu, PHP_EOL)); $l2_cache = trim($lscpu); } return $l2_cache; } public static function cpuinfo_core_count() { $core_count = self::read_cpuinfo_line('cpu cores'); if($core_count == false || !is_numeric($core_count)) { $core_count = self::read_cpuinfo_line('core id', false); if(is_numeric($core_count)) { // cpuinfo 'core id' begins counting at 0 $core_count += 1; } } if($core_count == false || !is_numeric($core_count)) { $core_count = self::cpuinfo_thread_count(); } return $core_count; } public static function cpuinfo_thread_count() { $thread_count = self::read_cpuinfo_line('processor', false); if(is_numeric($thread_count)) { // cpuinfo 'processor' begins counting at 0 $thread_count += 1; } return $thread_count; } public static function cpuinfo_cache_size() { // CPU cache size in KB $cache_size = self::read_cpuinfo_line('cache size'); if(substr($cache_size, -3) == ' KB') { $cache_size = substr($cache_size, 0, -3); } else { $cache_size = null; } return $cache_size; } } ?> phoronix-test-suite/pts-core/objects/phodevi/components/phodevi_gpu.php0000644000175000017500000010751212223041131026643 0ustar michaelmichael. */ class phodevi_gpu extends phodevi_device_interface { public static function read_property($identifier) { switch($identifier) { case 'identifier': $property = new phodevi_device_property('gpu_string', phodevi::std_caching); break; case 'model': $property = new phodevi_device_property('gpu_model', phodevi::smart_caching); break; case 'frequency': $property = new phodevi_device_property('gpu_frequency_string', phodevi::std_caching); break; case 'stock-frequency': $property = new phodevi_device_property('gpu_stock_frequency', phodevi::std_caching); break; case 'memory-capacity': $property = new phodevi_device_property('gpu_memory_size', phodevi::smart_caching); break; case 'aa-level': $property = new phodevi_device_property('gpu_aa_level', phodevi::no_caching); break; case 'af-level': $property = new phodevi_device_property('gpu_af_level', phodevi::no_caching); break; case 'compute-cores': $property = new phodevi_device_property('gpu_compute_cores', phodevi::smart_caching); break; case 'available-modes': $property = new phodevi_device_property('gpu_available_modes', phodevi::std_caching); break; case 'screen-resolution': $property = new phodevi_device_property('gpu_screen_resolution', phodevi::std_caching); break; case 'screen-resolution-string': $property = new phodevi_device_property('gpu_screen_resolution_string', phodevi::std_caching); break; case '2d-acceleration': $property = new phodevi_device_property('gpu_2d_acceleration', phodevi::std_caching); break; } return $property; } public static function gpu_2d_acceleration() { $xorg_log = isset(phodevi::$vfs->xorg_log) ? phodevi::$vfs->xorg_log : false; $accel_2d = false; if($xorg_log) { if(strpos($xorg_log, 'EXA(0)')) { $accel_2d = 'EXA'; } else if(stripos($xorg_log, 'GLAMOR acceleration')) { $accel_2d = 'GLAMOR'; } else if(strpos($xorg_log, 'SNA initialized')) { $accel_2d = 'SNA'; } else if(strpos($xorg_log, 'UXA(0)')) { $accel_2d = 'UXA'; } else if(strpos($xorg_log, 'Gallium3D XA')) { $accel_2d = 'Gallium3D XA'; } else if(strpos($xorg_log, 'shadowfb')) { $accel_2d = 'ShadowFB'; } } return $accel_2d; } public static function set_property($identifier, $args) { switch($identifier) { case 'screen-resolution': $property = self::gpu_set_resolution($args); break; } return $property; } public static function gpu_set_resolution($args) { if(count($args) != 2 || phodevi::is_windows() || phodevi::is_macosx() || !pts_client::executable_in_path('xrandr')) { return false; } $width = $args[0]; $height = $args[1]; shell_exec('xrandr -s ' . $width . 'x' . $height . ' 2>&1'); return phodevi::read_property('gpu', 'screen-resolution') == array($width, $height); // Check if video resolution set worked } public static function gpu_aa_level() { // Determine AA level if over-rode $aa_level = false; if(phodevi::is_nvidia_graphics()) { $nvidia_fsaa = phodevi_parser::read_nvidia_extension('FSAA'); switch($nvidia_fsaa) { case 1: $aa_level = '2x Bilinear'; break; case 5: $aa_level = '4x Bilinear'; break; case 7: $aa_level = '8x'; break; case 8: $aa_level = '16x'; break; case 10: $aa_level = '8xQ'; break; case 12: $aa_level = '16xQ'; break; } } else if(phodevi::is_ati_graphics() && phodevi::is_linux()) { $ati_fsaa = phodevi_linux_parser::read_amd_pcsdb('OpenGL,AntiAliasSamples'); $ati_fsaa_filter = phodevi_linux_parser::read_amd_pcsdb('OpenGL,AAF'); if(!empty($ati_fsaa)) { if($ati_fsaa_filter == '0x00000000') { // Filter: Box switch($ati_fsaa) { case '0x00000002': $aa_level = '2x Box'; break; case '0x00000004': $aa_level = '4x Box'; break; case '0x00000008': $aa_level = '8x Box'; break; } } else if($ati_fsaa_filter == '0x00000001') { // Filter: Narrow-tent switch($ati_fsaa) { case '0x00000002': $aa_level = '4x Narrow-tent'; break; case '0x00000004': $aa_level = '8x Narrow-tent'; break; case '0x00000008': $aa_level = '12x Narrow-tent'; break; } } else if($ati_fsaa_filter == '0x00000002') { // Filter: Wide-tent switch($ati_fsaa) { case '0x00000002': $aa_level = '6x Wide-tent'; break; case '0x00000004': $aa_level = '8x Wide-tent'; break; case '0x00000008': $aa_level = '16x Wide-tent'; break; } } else if($ati_fsaa_filter == '0x00000003') { // Filter: Edge-detect switch($ati_fsaa) { case '0x00000004': $aa_level = '12x Edge-detect'; break; case '0x00000008': $aa_level = '24x Edge-detect'; break; } } } } else if(phodevi::is_mesa_graphics()) { $gallium_msaa = getenv('GALLIUM_MSAA'); if(is_numeric($gallium_msaa) && $gallium_msaa > 0) { // Simple test to try to figure out if the GALLIUM_MSAA anti-aliasing value was forced $aa_level = $gallium_msaa . 'x MSAA'; } } else if(getenv('__GL_FSAA_MODE')) { $gl_msaa = getenv('__GL_FSAA_MODE'); if(is_numeric($gl_msaa) && $gl_msaa > 0) { $aa_level = '__GL_FSAA_MODE=' . $gallium_msaa; } } return $aa_level; } public static function gpu_af_level() { // Determine AF level if over-rode $af_level = false; if(phodevi::is_nvidia_graphics()) { $nvidia_af = phodevi_parser::read_nvidia_extension('LogAniso'); switch($nvidia_af) { case 1: $af_level = '2x'; break; case 2: $af_level = '4x'; break; case 3: $af_level = '8x'; break; case 4: $af_level = '16x'; break; } } else if(phodevi::is_ati_graphics() && phodevi::is_linux()) { $ati_af = phodevi_linux_parser::read_amd_pcsdb('OpenGL,AnisoDegree'); if(!empty($ati_af)) { switch($ati_af) { case '0x00000002': $af_level = '2x'; break; case '0x00000004': $af_level = '4x'; break; case '0x00000008': $af_level = '8x'; break; case '0x00000010': $af_level = '16x'; break; } } } else if(getenv('__GL_LOG_MAX_ANISO')) { $max_aniso = getenv('__GL_LOG_MAX_ANISO'); if(is_numeric($max_aniso) && $max_aniso > 0) { switch($max_aniso) { case 1: $max_aniso = '2x'; break; case 2: $max_aniso = '4x'; break; case 3: $max_aniso = '8x'; break; case 4: $max_aniso = '16x'; break; } $af_level = $max_aniso; } } return $af_level; } public static function gpu_compute_cores() { // Determine AF level if over-rode $cores = 0; if(phodevi::is_nvidia_graphics()) { $cores = phodevi_parser::read_nvidia_extension('CUDACores'); } return $cores; } public static function gpu_xrandr_resolution() { $resolution = false; if(pts_client::executable_in_path('xrandr') && getenv('DISPLAY')) { // Read resolution from xrandr $info = shell_exec('xrandr 2>&1 | grep "*"'); if(strpos($info, '*') !== false) { $res = pts_strings::trim_explode('x', $info); if(isset($res[1])) { $res[0] = substr($res[0], strrpos($res[0], ' ')); $res[1] = substr($res[1], 0, strpos($res[1], ' ')); $res = array_map('trim', $res); if(is_numeric($res[0]) && is_numeric($res[1])) { $resolution = array($res[0], $res[1]); } } } } return $resolution; } public static function gpu_screen_resolution() { $resolution = false; if((($default_mode = getenv('DEFAULT_VIDEO_MODE')) != false)) { $default_mode = explode('x', $default_mode); if(count($default_mode) == 2 && is_numeric($default_mode[0]) && is_numeric($default_mode[1])) { return $default_mode; } } if(phodevi::is_macosx()) { $info = pts_strings::trim_explode(' ', phodevi_osx_parser::read_osx_system_profiler('SPDisplaysDataType', 'Resolution')); $resolution = array(); $resolution[0] = $info[0]; $resolution[1] = $info[2]; } else if(phodevi::is_linux() || phodevi::is_bsd() || phodevi::is_solaris()) { if(phodevi::is_linux()) { // Before calling xrandr first try to get the resolution through KMS path foreach(pts_file_io::glob('/sys/class/drm/card*/*/modes') as $connector_path) { $connector_path = dirname($connector_path) . '/'; if(is_file($connector_path . 'enabled') && pts_file_io::file_get_contents($connector_path . 'enabled') == 'enabled') { $mode = pts_arrays::first_element(explode("\n", pts_file_io::file_get_contents($connector_path . 'modes'))); $info = pts_strings::trim_explode('x', $mode); if(count($info) == 2) { $resolution = $info; break; } } } } if($resolution == false && pts_client::executable_in_path('xrandr')) { $resolution = self::gpu_xrandr_resolution(); } if($resolution == false && phodevi::is_nvidia_graphics()) { // Way to find resolution through NVIDIA's NV-CONTROL extension // But rely upon xrandr first since when using NVIDIA TwinView the reported FrontEndResolution may be the smaller of the two if(($frontend_res = phodevi_parser::read_nvidia_extension('FrontendResolution')) != false) { $resolution = pts_strings::comma_explode($frontend_res); } } if($resolution == false) { // Fallback to reading resolution from xdpyinfo foreach(phodevi_parser::read_xdpy_monitor_info() as $monitor_line) { $this_resolution = substr($monitor_line, strpos($monitor_line, ': ') + 2); $this_resolution = substr($this_resolution, 0, strpos($this_resolution, ' ')); $this_resolution = explode('x', $this_resolution); if(count($this_resolution) == 2 && is_numeric($this_resolution[0]) && is_numeric($this_resolution[1])) { $resolution = $this_resolution; break; } } } if($resolution == false && is_readable('/sys/class/graphics/fb0/virtual_size')) { // As last fall-back try reading size of fb $virtual_size = explode(',', pts_file_io::file_get_contents('/sys/class/graphics/fb0/virtual_size')); if(count($virtual_size) == 2 && is_numeric($virtual_size[0]) && is_numeric($virtual_size[1])) { $resolution = $virtual_size; } } } return $resolution == false ? array(-1, -1) : $resolution; } public static function gpu_screen_resolution_string() { // Return the current screen resolution $resolution = implode('x', phodevi::read_property('gpu', 'screen-resolution')); if($resolution == '-1x-1') { $resolution = null; } return $resolution; } public static function gpu_available_modes() { // XRandR available modes $current_resolution = phodevi::read_property('gpu', 'screen-resolution'); $current_pixel_count = $current_resolution[0] * $current_resolution[1]; $available_modes = array(); $supported_ratios = array(1.60, 1.25, 1.33, 1.70, 1.71, 1.78); $ignore_modes = array( array(640, 400), array(720, 480), array(832, 624), array(960, 540), array(960, 600), array(896, 672), array(928, 696), array(960, 720), array(1152, 864), array(1280, 720), array(1360, 768), array(1776, 1000), array(1792, 1344), array(1800, 1440), array(1856, 1392), array(2048, 1536) ); if($override_check = (($override_modes = getenv('OVERRIDE_VIDEO_MODES')) != false)) { $override_modes = pts_strings::comma_explode($override_modes); for($i = 0; $i < count($override_modes); $i++) { $override_modes[$i] = explode('x', $override_modes[$i]); } } // Attempt reading available modes from xrandr if(pts_client::executable_in_path('xrandr') && !phodevi::is_macosx()) // MacOSX has xrandr but currently on at least my setup will emit a Bus Error when called { $xrandr_lines = array_reverse(explode("\n", shell_exec('xrandr 2>&1'))); foreach($xrandr_lines as $xrandr_mode) { if(($cut_point = strpos($xrandr_mode, '(')) > 0) { $xrandr_mode = substr($xrandr_mode, 0, $cut_point); } $res = pts_strings::trim_explode('x', $xrandr_mode); if(count($res) == 2) { $res[0] = substr($res[0], strrpos($res[0], ' ')); $res[1] = substr($res[1], 0, strpos($res[1], ' ')); if(is_numeric($res[0]) && is_numeric($res[1])) { $m = array($res[0], $res[1]); if(!in_array($m, $available_modes)) { // Don't repeat modes array_push($available_modes, $m); } } } } } if(count($available_modes) <= 2) { // Fallback to providing stock modes $stock_modes = array( array(800, 600), array(1024, 768), array(1280, 800), array(1280, 1024), array(1400, 900), array(1400, 1050), array(1600, 900), array(1680, 1050), array(1600, 1200), array(1920, 1080), array(1920, 1200), array(2560, 1600)); $available_modes = array(); for($i = 0; $i < count($stock_modes); $i++) { if($stock_modes[$i][0] <= $current_resolution[0] && $stock_modes[$i][1] <= $current_resolution[1]) { array_push($available_modes, $stock_modes[$i]); } } } if(!in_array(phodevi::read_property('gpu', 'screen-resolution'), $available_modes)) { array_push($available_modes, phodevi::read_property('gpu', 'screen-resolution')); } foreach($available_modes as $mode_index => $mode) { $this_ratio = pts_math::set_precision($mode[0] / $mode[1], 2); if($override_check && !in_array($mode, $override_modes)) { // Using override modes and this mode is not present unset($available_modes[$mode_index]); } else if($current_pixel_count > 614400 && ($mode[0] * $mode[1]) < 480000 && stripos(phodevi::read_name('gpu'), 'llvmpipe') === false) { // For displays larger than 1024 x 600, drop modes below 800 x 600 unless llvmpipe is being used unset($available_modes[$mode_index]); } else if($current_pixel_count > 480000 && !in_array($this_ratio, $supported_ratios)) { // For displays larger than 800 x 600, ensure reading from a supported ratio unset($available_modes[$mode_index]); } else if(in_array($mode, $ignore_modes)) { // Mode is to be ignored unset($available_modes[$mode_index]); } } // Sort available modes in order $unsorted_modes = $available_modes; $available_modes = array(); $mode_pixel_counts = array(); foreach($unsorted_modes as $this_mode) { if(count($this_mode) == 2) { array_push($mode_pixel_counts, $this_mode[0] * $this_mode[1]); } } // Sort resolutions by true pixel count resolution sort($mode_pixel_counts); foreach($mode_pixel_counts as &$mode_pixel_count) { foreach($unsorted_modes as $mode_index => $mode) { if($mode[0] * $mode[1] == $mode_pixel_count) { array_push($available_modes, $mode); unset($unsorted_modes[$mode_index]); break; } } } if(count($available_modes) == 0 && $override_check) { // Write in the non-standard modes that were overrode foreach($override_modes as $mode) { if(is_array($mode) && count($mode) == 2) { array_push($available_modes, $mode); } } } return $available_modes; } public static function gpu_memory_size() { // Graphics memory capacity $video_ram = -1; if(($vram = getenv('VIDEO_MEMORY')) != false && is_numeric($vram)) { $video_ram = $vram; } else if(is_file('/sys/kernel/debug/dri/0/memory')) { // This is how some of the Nouveau DRM VRAM is reported $memory = file_get_contents('/sys/kernel/debug/dri/0/memory'); if(($x = strpos($memory, 'VRAM total: ')) !== false) { $memory = substr($memory, ($x + 12)); if(($x = strpos($memory, 'KiB')) !== false) { $memory = substr($memory, 0, $x); if(is_numeric($memory)) { $video_ram = $memory / 1024; } } } } else if(phodevi::is_nvidia_graphics() && ($NVIDIA = phodevi_parser::read_nvidia_extension('VideoRam')) > 0) // NVIDIA blob { $video_ram = $NVIDIA / 1024; } else if(phodevi::is_macosx()) { $info = phodevi_osx_parser::read_osx_system_profiler('SPDisplaysDataType', 'VRAM'); $info = explode(' ', $info); $video_ram = $info[0]; if($info[1] == 'GB') { $video_ram *= 1024; } } if($video_ram == -1 && isset(phodevi::$vfs->xorg_log)) { // Attempt Video RAM detection using X log // fglrx driver reports video memory to: (--) fglrx(0): VideoRAM: XXXXXX kByte, Type: DDR // xf86-video-ati, xf86-video-intel, and xf86-video-radeonhd also report their memory information in a similar format $info = phodevi::$vfs->xorg_log; if(($pos = stripos($info, 'RAM:') + 5) > 5 || ($pos = strpos($info, 'RAM=') + 4) > 4) { $info = substr($info, $pos); $info = substr($info, 0, strpos($info, ' ')); if(!is_numeric($info) && ($cut = strpos($info, ','))) { $info = substr($info, 0, $cut); } if(is_numeric($info) && $info > 65535) { $video_ram = intval($info) / 1024; } } } if($video_ram == -1 && isset(phodevi::$vfs->dmesg)) { // Fallback to try to find vRAM from dmesg $info = phodevi::$vfs->dmesg; if(($x = strpos($info, 'Detected VRAM RAM=')) !== false) { // Radeon DRM at least reports: [drm] Detected VRAM RAM=2048M, BAR=256M $info = substr($info, $x + 18); $info = substr($info, 0, strpos($info, 'M')); } else if(($x = strpos($info, 'M of VRAM')) !== false) { // Radeon DRM around Linux ~3.0 reports e.g.: [drm] radeon: 2048M of VRAM memory ready $info = substr($info, 0, $x); $info = substr($info, strrpos($info, ' ') + 1); } else if(($x = strpos($info, 'MiB VRAM')) !== false) { // Nouveau DRM around Linux ~3.0 reports e.g.: [drm] nouveau XXX: Detected 1024MiB VRAM $info = substr($info, 0, $x); $info = substr($info, strrpos($info, ' ') + 1); } else if(($x = strpos($info, 'VRAM: ')) !== false) { // Nouveau DRM around Linux ~3.6 reports e.g.: DRM] VRAM: 512 MiB $info = substr($info, ($x + 6)); $info = substr($info, 0, strpos($info, ' ')); } if(is_numeric($info)) { $video_ram = $info; } } if($video_ram == -1 || !is_numeric($video_ram) || $video_ram < 64) { $video_ram = 64; // default to 64MB of video RAM as something sane... } return $video_ram; } public static function gpu_string() { $info = phodevi_parser::read_glx_renderer(); if(stripos($info, 'llvmpipe')) { return 'LLVMpipe'; } else { return phodevi::read_property('gpu', 'model') . ' ' . phodevi::read_property('gpu', 'frequency'); } } public static function gpu_frequency_string() { $freq = phodevi::read_property('gpu', 'stock-frequency'); $freq_string = null; if($freq[0] != 0) { $freq_string = $freq[0]; if($freq[1] != 0) { $freq_string .= '/' . $freq[1]; } $freq_string .= 'MHz'; } return ($freq_string != null ? ' (' . $freq_string . ')' : null); } public static function gpu_stock_frequency() { // Graphics processor stock frequency $core_freq = 0; $mem_freq = 0; if(phodevi::is_nvidia_graphics() && phodevi::is_macosx() == false) // NVIDIA GPU { // GPUDefault3DClockFreqs is the default and does not show under/over-clocking $clock_freqs_3d = pts_strings::comma_explode(phodevi_parser::read_nvidia_extension('GPU3DClockFreqs')); if(is_array($clock_freqs_3d) && isset($clock_freqs_3d[1])) { list($core_freq, $mem_freq) = $clock_freqs_3d; } } else if(phodevi::is_ati_graphics() && phodevi::is_linux()) // ATI GPU { $od_clocks = phodevi_linux_parser::read_ati_overdrive('CurrentPeak'); if(is_array($od_clocks) && count($od_clocks) >= 2) // ATI OverDrive { list($core_freq, $mem_freq) = $od_clocks; } } else if(phodevi::is_mesa_graphics()) { switch(phodevi::read_property('system', 'display-driver')) { case 'nouveau': if(is_file('/sys/class/drm/card0/device/performance_level')) { /* EXAMPLE OUTPUTS: memory 1000MHz core 500MHz voltage 1300mV fanspeed 100% 3: memory 333MHz core 500MHz shader 1250MHz fanspeed 100% c: memory 333MHz core 500MHz shader 1250MHz */ $performance_level = pts_file_io::file_get_contents('/sys/class/drm/card0/device/performance_level'); $performance_level = explode(' ', $performance_level); $core_string = array_search('core', $performance_level); if($core_string !== false && isset($performance_level[($core_string + 1)])) { $core_string = str_ireplace('MHz', null, $performance_level[($core_string + 1)]); if(is_numeric($core_string)) { $core_freq = $core_string; } } $mem_string = array_search('memory', $performance_level); if($mem_string !== false && isset($performance_level[($mem_string + 1)])) { $mem_string = str_ireplace('MHz', null, $performance_level[($mem_string + 1)]); if(is_numeric($mem_string)) { $mem_freq = $mem_string; } } } break; case 'radeon': if(isset(phodevi::$vfs->radeon_pm_info)) { // radeon_pm_info should be present with Linux 2.6.34+ but was changed with Linux 3.11 Radeon DPM if(stripos(phodevi::$vfs->radeon_pm_info, 'default')) { foreach(pts_strings::trim_explode("\n", phodevi::$vfs->radeon_pm_info) as $pm_line) { if($pm_line == null) { continue; } list($descriptor, $value) = pts_strings::colon_explode($pm_line); switch($descriptor) { case 'default engine clock': $core_freq = pts_arrays::first_element(explode(' ', $value)) / 1000; break; case 'default memory clock': $mem_freq = pts_arrays::first_element(explode(' ', $value)) / 1000; break; } } } } if($core_freq == null) { // Attempt to read the LAST power level reported to dmesg, this is the current way for Radeon DPM on Linux 3.11+ $dmesg_parse = isset(phodevi::$vfs->dmesg) ? phodevi::$vfs->dmesg : null; if(($x = strrpos($dmesg_parse, ' sclk:'))) { $dmesg_parse = substr($dmesg_parse, $x); $dmesg_parse = explode(' ', substr($dmesg_parse, 0, strpos($dmesg_parse, PHP_EOL))); $sclk = array_search('sclk:', $dmesg_parse); if($sclk !== false && isset($dmesg_parse[($sclk + 1)]) && is_numeric($dmesg_parse[($sclk + 1)])) { $sclk = $dmesg_parse[($sclk + 1)]; if($sclk > 10000) { $sclk = $sclk / 100; } $core_freq = $sclk; } $mclk = array_search('mclk:', $dmesg_parse); if($mclk !== false && isset($dmesg_parse[($mclk + 1)]) && is_numeric($dmesg_parse[($mclk + 1)])) { $mclk = $dmesg_parse[($mclk + 1)]; if($mclk > 10000) { $mclk = $mclk / 100; } $mem_freq = $mclk; } } } if($core_freq == null) { // Old ugly way of handling the clock information $log_parse = isset(phodevi::$vfs->xorg_log) ? phodevi::$vfs->xorg_log : null; if(($engine_clock = strpos($log_parse, 'Default Engine Clock: '))) { $core_freq = substr($log_parse, $engine_clock + 22); $core_freq = substr($core_freq, 0, strpos($core_freq, "\n")); $core_freq = is_numeric($core_freq) ? $core_freq / 1000 : 0; if($core_freq && ($mem_clock = strpos($log_parse, 'Default Memory Clock: '))) { $mem_freq = substr($log_parse, $mem_clock + 22); $mem_freq = substr($mem_freq, 0, strpos($mem_freq, "\n")); $mem_freq = is_numeric($mem_freq) ? $mem_freq / 1000 : 0; } else { $core_freq = 0; } } } break; case 'intel': // try to read the maximum dynamic frequency if(is_file('/sys/class/drm/card0/gt_max_freq_mhz')) { $gt_max_freq_mhz = pts_file_io::file_get_contents('/sys/class/drm/card0/gt_max_freq_mhz'); if(is_numeric($gt_max_freq_mhz) && $gt_max_freq_mhz > 100) { // Tested on Linux 3.11. Assume the max frequency on any competent GPU is beyond 100MHz $core_freq = $gt_max_freq_mhz; } } if($core_freq == 0 && is_file('/sys/kernel/debug/dri/0/i915_max_freq')) { $i915_max_freq = pts_file_io::file_get_contents('/sys/kernel/debug/dri/0/i915_max_freq'); $freq_mhz = substr($i915_max_freq, strpos($i915_max_freq, ': ') + 2); if(is_numeric($freq_mhz)) { $core_freq = $freq_mhz; } } // Fallback to base frequency if($core_freq == 0 && isset(phodevi::$vfs->i915_cur_delayinfo)) { $i915_cur_delayinfo = phodevi::$vfs->i915_cur_delayinfo; $freq = strpos($i915_cur_delayinfo, 'Max overclocked frequency: '); if($freq === false) { $freq = strpos($i915_cur_delayinfo, 'Max non-overclocked (RP0) frequency: '); } if($freq === false) { $freq = strpos($i915_cur_delayinfo, 'Nominal (RP1) frequency: '); } if($freq !== false) { $freq_mhz = substr($i915_cur_delayinfo, strpos($i915_cur_delayinfo, ': ', $freq) + 2); $freq_mhz = trim(substr($freq_mhz, 0, strpos($freq_mhz, 'MHz'))); if(is_numeric($freq_mhz)) { $core_freq = $freq_mhz; } } } break; } } if(!is_numeric($core_freq)) { $core_freq = 0; } if(!is_numeric($mem_freq)) { $mem_freq = 0; } return array($core_freq, $mem_freq); } public static function gpu_model() { // Report graphics processor string $info = phodevi_parser::read_glx_renderer(); $video_ram = phodevi::read_property('gpu', 'memory-capacity'); if(phodevi::is_ati_graphics() && phodevi::is_linux()) { $crossfire_status = phodevi_linux_parser::read_amd_pcsdb('SYSTEM/Crossfire/chain/*,Enable'); $crossfire_status = pts_arrays::to_array($crossfire_status); $crossfire_card_count = 0; for($i = 0; $i < count($crossfire_status); $i++) { if($crossfire_status[$i] == '0x00000001') { $crossfire_card_count += 2; // For now assume each chain is 2 cards, but proper way would be NumSlaves + 1 } } $adapters = phodevi_linux_parser::read_amd_graphics_adapters(); if(count($adapters) > 0) { $video_ram = $video_ram > 64 ? ' ' . $video_ram . 'MB' : null; // assume more than 64MB of vRAM if($crossfire_card_count > 1 && $crossfire_card_count <= count($adapters)) { $unique_adapters = array_unique($adapters); if(count($unique_adapters) == 1) { if(strpos($adapters[0], 'X2') > 0 && $crossfire_card_count > 1) { $crossfire_card_count -= 1; } $info = $crossfire_card_count . ' x ' . $adapters[0] . $video_ram . ' CrossFire'; } else { $info = implode(', ', $unique_adapters) . ' CrossFire'; } } else { $info = $adapters[0] . $video_ram; } } } else if(phodevi::is_macosx()) { $system_profiler_info = implode(' + ', phodevi_osx_parser::read_osx_system_profiler('SPDisplaysDataType', 'ChipsetModel', true)); if(!empty($system_profiler_info)) { $info = $system_profiler_info; } } else if(phodevi::is_nvidia_graphics()) { if($info == null) { if(pts_client::executable_in_path('nvidia-settings')) { $nv_gpus = shell_exec('nvidia-settings -q gpus 2>&1'); // TODO: search for more than one GPU $nv_gpus = substr($nv_gpus, strpos($nv_gpus, '[0]')); $nv_gpus = substr($nv_gpus, strpos($nv_gpus, '(') + 1); $nv_gpus = substr($nv_gpus, 0, strpos($nv_gpus, ')')); if(stripos($nv_gpus, 'GeForce') !== false || stripos($nv_gpus, 'Quadro') !== false) { $info = $nv_gpus; } } } $sli_mode = phodevi_parser::read_nvidia_extension('SLIMode'); if(!empty($sli_mode) && $sli_mode != 'Off') { $info .= ' SLI'; } } else if(phodevi::is_solaris()) { if(($cut = strpos($info, 'DRI ')) !== false) { $info = substr($info, ($cut + 4)); } if(($cut = strpos($info, ' Chipset')) !== false) { $info = substr($info, 0, $cut); } if($info == false && isset(phodevi::$vfs->xorg_log)) { $xorg_log = phodevi::$vfs->xorg_log; if(($x = strpos($xorg_log, '(0): Chipset: ')) !== false) { $xorg_log = substr($xorg_log, ($x + 14)); $xorg_log = str_replace(array('(R)', '"'), null, substr($xorg_log, 0, strpos($xorg_log, PHP_EOL))); if(($c = strpos($xorg_log, '[')) || ($c = strpos($xorg_log, '('))) { $xorg_log = substr($xorg_log, 0, $c); } if(phodevi::is_product_string($xorg_log)) { $info = $xorg_log; } } } } else if(phodevi::is_bsd()) { $drm_info = phodevi_bsd_parser::read_sysctl('dev.drm.0.%desc'); if(!$drm_info) { $drm_info = phodevi_bsd_parser::read_sysctl('dev.nvidia.0.%desc'); } if(!$drm_info) { $agp_info = phodevi_bsd_parser::read_sysctl('dev.agp.0.%desc'); if($agp_info != false) { $info = $agp_info; } } else { $info = $drm_info; } if($info == null && isset(phodevi::$vfs->xorg_log)) { $xorg_log = phodevi::$vfs->xorg_log; if(($e = strpos($xorg_log, ' at 01@00:00:0')) !== false) { $xorg_log = substr($xorg_log, 0, $e); $info = substr($xorg_log, strrpos($xorg_log, 'Found ') + 6); } } } else if(phodevi::is_windows()) { $info = phodevi_windows_parser::read_cpuz('Display Adapters', 'Name'); } if(empty($info) || strpos($info, 'Mesa ') !== false || strpos($info, 'Gallium ') !== false) { if(phodevi::is_windows() == false) { $info_pci = phodevi_linux_parser::read_pci('VGA compatible controller', false); if(!empty($info_pci)) { $info = $info_pci; if(strpos($info, 'Intel 2nd Generation Core Family') !== false || strpos($info, 'Gen Core') !== false) { // Try to come up with a better non-generic string $was_reset = false; if(isset(phodevi::$vfs->xorg_log)) { /* $ cat /var/log/Xorg.0.log | grep -i Chipset [ 8.421] (II) intel: Driver for Intel Integrated Graphics Chipsets: i810, [ 8.421] (II) VESA: driver for VESA chipsets: vesa [ 8.423] (II) intel(0): Integrated Graphics Chipset: Intel(R) Sandybridge Mobile (GT2+) [ 8.423] (--) intel(0): Chipset: "Sandybridge Mobile (GT2+)" */ $xorg_log = phodevi::$vfs->xorg_log; if(($x = strpos($xorg_log, 'Integrated Graphics Chipset: ')) !== false) { $xorg_log = substr($xorg_log, ($x + 29)); $xorg_log = str_replace(array('(R)', '"'), null, substr($xorg_log, 0, strpos($xorg_log, PHP_EOL))); if(stripos($xorg_log, 'Intel') === false) { $xorg_log = 'Intel ' . $xorg_log; } // if string is too long, likely not product if(!isset($xorg_log[45])) { $info = $xorg_log; $was_reset = true; } } else if(($x = strpos($xorg_log, '(0): Chipset: ')) !== false) { $xorg_log = substr($xorg_log, ($x + 14)); $xorg_log = str_replace(array('(R)', '"'), null, substr($xorg_log, 0, strpos($xorg_log, PHP_EOL))); if(stripos($xorg_log, 'Intel') === false) { $xorg_log = 'Intel ' . $xorg_log; } // if string is too long, likely not product if(!isset($xorg_log[45])) { $info = $xorg_log; $was_reset = true; } } } if($was_reset == false && isset(phodevi::$vfs->i915_capabilities)) { $i915_caps = phodevi::$vfs->i915_capabilities; if(($x = strpos($i915_caps, 'gen: ')) !== false) { $gen = substr($i915_caps, ($x + 5)); $gen = substr($gen, 0, strpos($gen, PHP_EOL)); if(is_numeric($gen)) { $info = 'Intel Gen' . $gen; if(strpos($i915_caps, 'is_mobile: yes') !== false) { $info .= ' Mobile'; } } } } } } } if(($start_pos = strpos($info, ' DRI ')) > 0) { $info = substr($info, $start_pos + 5); } if(empty($info) && isset(phodevi::$vfs->xorg_log)) { $log_parse = phodevi::$vfs->xorg_log; $log_parse = substr($log_parse, strpos($log_parse, 'Chipset') + 8); $log_parse = substr($log_parse, 0, strpos($log_parse, 'found')); if(strpos($log_parse, '(--)') === false && strlen(str_ireplace(array('ATI', 'NVIDIA', 'VIA', 'Intel'), '', $log_parse)) != strlen($log_parse)) { $info = $log_parse; } } if(empty($info) && is_readable('/sys/class/graphics/fb0/name')) { switch(pts_file_io::file_get_contents('/sys/class/graphics/fb0/name')) { case 'omapdrm': $info = 'Texas Instruments OMAP'; // The OMAP DRM driver currently is for OMAP2/3/4 hardware break; case 'exynos': $info = 'Samsung EXYNOS'; // The Exynos DRM driver break; case 'tegra_fb': $info = 'NVIDIA TEGRA'; // The Exynos DRM driver break; default: if(is_file('/dev/mali')) { $info = 'ARM Mali'; // One of the ARM Mali models } break; } } if(substr($info, -1) == ')' && ($open_p = strrpos($info, '(')) != false) { $end_check = strpos($info, ' ', $open_p); $to_check = substr($info, ($open_p + 1), ($end_check - $open_p - 1)); // Don't report card revision from PCI info if($to_check == 'rev') { $info = substr($info, 0, $open_p - 1); } } } if(($bracket_open = strpos($info, '[')) !== false) { // Report only the information inside the brackets if it's more relevant... // Mainly with Linux systems where the PCI information is reported like 'nVidia GF104 [GeForce GTX 460]' if(($bracket_close = strpos($info, ']', ($bracket_open + 1))) !== false) { $inside_bracket = substr($info, ($bracket_open + 1), ($bracket_close - $bracket_open - 1)); if(stripos($inside_bracket, 'Quadro') !== false || stripos($inside_bracket, 'GeForce') !== false) { $info = $inside_bracket . ' ' . substr($info, ($bracket_close + 1)); } else if(stripos($inside_bracket, 'Radeon') !== false || stripos($inside_bracket, 'Fire') !== false || stripos($inside_bracket, 'Fusion') !== false) { $info = $inside_bracket . ' ' . substr($info, ($bracket_close + 1)); } } } if(stripos($info, 'NVIDIA') === false && (stripos($info, 'Quadro') !== false || stripos($info, 'GeForce') !== false)) { $info = 'NVIDIA' . ' ' . $info; } else if((stripos($info, 'ATI') === false && stripos($info, 'AMD') === false) && (stripos($info, 'Radeon') !== false || stripos($info, 'Fire') !== false || stripos($info, 'Fusion') !== false)) { // Fire would be for FireGL or FirePro hardware $info = 'AMD ' . $info; } if(phodevi::is_linux() && ($vendor = phodevi_linux_parser::read_pci_subsystem_value('VGA compatible controller')) != null && stripos($info, $vendor) === false && (stripos($info, 'AMD') !== false || stripos($info, 'NVIDIA') !== false)) { $info = $vendor . ' ' . $info; } if($video_ram > 64 && strpos($info, $video_ram) == false) // assume more than 64MB of vRAM { $info .= ' ' . $video_ram . 'MB'; } $clean_phrases = array('OpenGL Engine'); $info = str_replace($clean_phrases, null, $info); return $info; } } ?> phoronix-test-suite/pts-core/objects/phodevi/components/phodevi_monitor.php0000644000175000017500000001413312157226372027555 0ustar michaelmichael. */ class phodevi_monitor extends phodevi_device_interface { public static function read_property($identifier) { switch($identifier) { case 'identifier': $property = new phodevi_device_property('monitor_string', phodevi::smart_caching); break; case 'count': $property = new phodevi_device_property('monitor_count', phodevi::std_caching); break; case 'layout': $property = new phodevi_device_property('monitor_layout', phodevi::std_caching); break; case 'modes': $property = new phodevi_device_property('monitor_modes', phodevi::std_caching); break; } return $property; } public static function monitor_string() { if(phodevi::is_macosx()) { $system_profiler = shell_exec('system_profiler SPDisplaysDataType 2>&1'); $system_profiler = substr($system_profiler, strrpos($system_profiler, 'Displays:')); $system_profiler = substr($system_profiler, strpos($system_profiler, "\n")); $monitor = trim(substr($system_profiler, 0, strpos($system_profiler, ':'))); if($monitor == 'Display Connector') { $monitor = null; } } else if(isset(phodevi::$vfs->xorg_log)) { $log_parse = phodevi::$vfs->xorg_log; $offset = 0; $monitor = array(); while(($monitor_name = strpos($log_parse, 'Monitor name:', $offset)) !== false) { $log_parse = substr($log_parse, $monitor_name + 14); $m = trim(substr($log_parse, 0, strpos($log_parse, "\n"))); if(!empty($m)) { array_push($monitor, $m); } } $monitor = implode(' + ', $monitor); } return empty($monitor) ? false : $monitor; } public static function monitor_count() { // Report number of connected/enabled monitors $monitor_count = 0; // First try reading number of monitors from xdpyinfo $monitor_count = count(phodevi_parser::read_xdpy_monitor_info()); if($monitor_count == 0) { // Fallback support for ATI and NVIDIA if phodevi_parser::read_xdpy_monitor_info() fails if(phodevi::is_nvidia_graphics()) { $enabled_displays = phodevi_parser::read_nvidia_extension('EnabledDisplays'); switch($enabled_displays) { case '0x00010000': $monitor_count = 1; break; case '0x00010001': $monitor_count = 2; break; default: $monitor_count = 1; break; } } else if(phodevi::is_ati_graphics() && phodevi::is_linux()) { $amdpcsdb_enabled_monitors = phodevi_linux_parser::read_amd_pcsdb('SYSTEM/BUSID-*/DDX,EnableMonitor'); $amdpcsdb_enabled_monitors = pts_arrays::to_array($amdpcsdb_enabled_monitors); foreach($amdpcsdb_enabled_monitors as $enabled_monitor) { foreach(pts_strings::comma_explode($enabled_monitor) as $monitor_connection) { $monitor_count++; } } } else { $monitor_count = 1; } } return $monitor_count; } public static function monitor_layout() { // Determine layout for multiple monitors $monitor_layout = array('CENTER'); if(phodevi::read_property('monitor', 'count') > 1) { $xdpy_monitors = phodevi_parser::read_xdpy_monitor_info(); $hit_0_0 = false; for($i = 0; $i < count($xdpy_monitors); $i++) { $monitor_position = explode('@', $xdpy_monitors[$i]); $monitor_position = trim($monitor_position[1]); $monitor_position_x = substr($monitor_position, 0, strpos($monitor_position, ',')); $monitor_position_y = substr($monitor_position, strpos($monitor_position, ',') + 1); if($monitor_position == '0,0') { $hit_0_0 = true; } else if($monitor_position_x > 0 && $monitor_position_y == 0) { array_push($monitor_layout, ($hit_0_0 ? 'RIGHT' : 'LEFT')); } else if($monitor_position_x == 0 && $monitor_position_y > 0) { array_push($monitor_layout, ($hit_0_0 ? 'LOWER' : 'UPPER')); } } if(count($monitor_layout) == 1) { // Something went wrong with xdpy information, go to fallback support if(phodevi::is_ati_graphics() && phodevi::is_linux()) { $amdpcsdb_monitor_layout = phodevi_linux_parser::read_amd_pcsdb('SYSTEM/BUSID-*/DDX,DesktopSetup'); $amdpcsdb_monitor_layout = pts_arrays::to_array($amdpcsdb_monitor_layout); foreach($amdpcsdb_monitor_layout as $card_monitor_configuration) { switch($card_monitor_configuration) { case 'horizontal': array_push($monitor_layout, 'RIGHT'); break; case 'horizontal,reverse': array_push($monitor_layout, 'LEFT'); break; case 'vertical': array_push($monitor_layout, 'ABOVE'); break; case 'vertical,reverse': array_push($monitor_layout, 'BELOW'); break; } } } } } return implode(',', $monitor_layout); } public static function monitor_modes() { // Determine resolutions for each monitor $resolutions = array(); if(phodevi::read_property('monitor', 'count') == 1) { array_push($resolutions, phodevi::read_property('gpu', 'screen-resolution-string')); } else { foreach(phodevi_parser::read_xdpy_monitor_info() as $monitor_line) { $this_resolution = substr($monitor_line, strpos($monitor_line, ':') + 2); $this_resolution = substr($this_resolution, 0, strpos($this_resolution, ' ')); array_push($resolutions, $this_resolution); } } return implode(',', $resolutions); } } ?> phoronix-test-suite/pts-core/objects/phodevi/parsers/phodevi_parser.php0000644000175000017500000001621012117672537026656 0ustar michaelmichael. */ class phodevi_parser { public static function read_nvidia_extension($attribute) { // Read NVIDIA's NV Extension $nv_info = false; if(pts_client::executable_in_path('nvidia-settings')) { $info = shell_exec('nvidia-settings --query ' . $attribute . ' 2> /dev/null'); if(($pos = strpos($info, pts_strings::last_in_string($attribute, '/'))) > 0 && strpos($info, 'ERROR:') === false) { $nv_info = substr($info, strpos($info, '):') + 3); $nv_info = trim(substr($nv_info, 0, strpos($nv_info, "\n"))); if(substr($nv_info, -1) == '.') { $nv_info = substr($nv_info, 0, -1); } } } return $nv_info; } public static function read_xdpy_monitor_info() { // Read xdpyinfo monitor information return array(); static $monitor_info = null; if($monitor_info == null) { $monitor_info = array(); if(pts_client::executable_in_path('xdpyinfo')) { $info = trim(shell_exec('xdpyinfo -ext XINERAMA 2>&1 | grep head')); foreach(explode("\n", $info) as $xdpyinfo_line) { if(!empty($xdpyinfo_line) && strpos($xdpyinfo_line, '0x0') == false) { array_push($monitor_info, $xdpyinfo_line); } } } } return $monitor_info; } public static function read_glx_renderer() { if(isset(phodevi::$vfs->glxinfo)) { $info = phodevi::$vfs->glxinfo; } else if(PTS_IS_CLIENT && pts_client::executable_in_path('fglrxinfo')) { $info = shell_exec('fglrxinfo 2>&1'); } else { return false; } if(($pos = strpos($info, 'OpenGL renderer string:')) !== false) { $info = substr($info, $pos + 24); $info = trim(substr($info, 0, strpos($info, "\n"))); } else { $info = false; } if(stripos($info, 'Software Rasterizer') !== false) { $info = false; } return $info; } public static function read_hddtemp($disk = null) { // Read hard drive temperature using hddtemp $hdd_temperature = -1; if(pts_client::executable_in_path('hddtemp')) { if(empty($disk)) { $disks = glob('/dev/sd*'); if(count($disks) > 0) { $disk = array_shift($disks); } } // For most situations this won't work since hddtemp usually requires root access $info = trim(shell_exec('hddtemp ' . $disk . ' 2>&1')); if(($start_pos = strrpos($info, ': ')) > 0 && ($end_pos = strrpos($info, '°')) > $start_pos) { $temperature = substr($info, ($start_pos + 2), ($end_pos - $start_pos - 2)); if(is_numeric($temperature)) { $unit = substr($info, $end_pos + 2, 1); if($unit == 'F') { $temperature = round((($temperature - 32) * 5 / 9), 2); } $hdd_temperature = $temperature; } } } return $hdd_temperature; } public static function read_xorg_module_version($module) { $module_version = false; if(isset(phodevi::$vfs->xorg_log)) { $xorg_log = phodevi::$vfs->xorg_log; if(($module_start = strpos($xorg_log, $module)) > 0) { $xorg_log = substr($xorg_log, $module_start); $temp_version = substr($xorg_log, strpos($xorg_log, 'module version =') + 17); $temp_version = substr($temp_version, 0, strpos($temp_version, "\n")); if(is_numeric(str_replace('.', null, $temp_version))) { $module_version = $temp_version; } } } return $module_version; } public static function parse_equal_delimited_file($file, $key) { $return_value = false; foreach(explode("\n", pts_file_io::file_get_contents($file)) as $build_line) { list($descriptor, $value) = pts_strings::trim_explode('=', $build_line); if($descriptor == $key) { $return_value = $value; break; } } return $return_value; } public static function hardware_values_to_remove() { return array( 'empty', 'null', 'unknown', 'unknow', 'system manufacturer', 'system version', 'system name', 'system product name', 'to be filled by o.e.m.', 'not applicable', 'not specified', 'not available', 'oem', '00', 'none', '1234567890' ); } public static function software_glxinfo_version() { $info = false; if(isset(phodevi::$vfs->glxinfo)) { $glxinfo = phodevi::$vfs->glxinfo; } else if(PTS_IS_CLIENT && pts_client::executable_in_path('fglrxinfo')) { $glxinfo = shell_exec('fglrxinfo 2> /dev/null'); } foreach(array('OpenGL core profile version string:', 'OpenGL version string:') as $gl_v_string) { if($info == false && isset($glxinfo) && ($pos = strpos($glxinfo, $gl_v_string)) !== false) { $info = substr($glxinfo, $pos + strlen($gl_v_string)); $info = substr($info, 0, strpos($info, "\n")); $info = trim(str_replace(array(' Release', '(Core Profile)'), null, $info)); // The Catalyst Linux Driver now does something stupid for this string like: // 1.4 (2.1 (3.3.11005 Compatibility Profile Context)) if(($pos = strrpos($info, 'Compatibility Profile Context')) !== false && strpos($info, '(') != ($last_p = strrpos($info, '('))) { if(is_numeric(str_replace(array('(', '.', ' '), null, substr($info, 0, $last_p)))) { // This looks like a stupid Catalyst driver string, so grab the last GL version reported $info = str_replace(array('(', ')'), null, substr($info, ($last_p + 1))); break; } } } } return $info; } public static function software_glxinfo_glsl_version() { $info = false; if(isset(phodevi::$vfs->glxinfo)) { $glxinfo = phodevi::$vfs->glxinfo; } else if(PTS_IS_CLIENT && pts_client::executable_in_path('fglrxinfo')) { $glxinfo = shell_exec('fglrxinfo 2> /dev/null'); } foreach(array('OpenGL core profile shading language version string:', 'OpenGL shading language version string:') as $shader_v_string) { if(isset($glxinfo) && $info == false && ($pos = strpos($glxinfo, $shader_v_string)) !== false) { $info = substr($glxinfo, $pos + strlen($shader_v_string)); $info = substr($info, 0, strpos($info, "\n")); $info = trim($info); } } return $info; } public static function software_glxinfo_opengl_extensions() { $info = false; if(isset(phodevi::$vfs->glxinfo)) { $glxinfo = phodevi::$vfs->glxinfo; if(($pos = strpos($glxinfo, 'OpenGL extensions:')) !== false) { $info = substr($glxinfo, $pos + 19); $info = substr($info, 0, strpos($info, PHP_EOL . PHP_EOL)); $info = trim($info); } } return $info; } } ?> phoronix-test-suite/pts-core/objects/phodevi/parsers/phodevi_bsd_parser.php0000644000175000017500000000454312101626730027477 0ustar michaelmichael. */ class phodevi_bsd_parser { public static function read_sysctl($desc) { // Read sysctl, used by *BSDs $info = false; if(pts_client::executable_in_path('sysctl')) { $desc = pts_arrays::to_array($desc); for($i = 0; $i < count($desc) && empty($info); $i++) { $output = shell_exec('sysctl ' . $desc[$i] . ' 2>&1'); if((($point = strpos($output, ':')) > 0 || ($point = strpos($output, '=')) > 0) && strpos($output, 'unknown oid') === false && strpos($output, 'is invalid') === false && strpos($output, 'not available') === false) { $info = trim(substr($output, $point + 1)); } } } return $info; } public static function read_kenv($v) { $ret = null; if(pts_client::executable_in_path('kenv')) { $kenv = shell_exec('kenv 2> /dev/null'); $v = PHP_EOL . $v . '='; if(($x = strpos($kenv, $v)) !== false) { $ret = substr($kenv, ($x + strlen($v))); $ret = substr($ret, 0, strpos($ret, PHP_EOL)); if($ret[0] == '"' && $ret[(strlen($ret) - 1)] == '"') { $ret = substr($ret, 1, -1); } } } return $ret != 'empty' ? $ret : null; } public static function read_acpiconf($desc) { $info = false; if(pts_client::executable_in_path('acpiconf 2> /dev/null')) { $output = shell_exec('acpiconf -i0'); if(($point = strpos($output, $desc . ':')) !== false) { $info = substr($output, $point + strlen($desc) + 1); $info = substr($info, 0, strpos($info, "\n")); $info = trim($info); } } return $info; } } ?> phoronix-test-suite/pts-core/objects/phodevi/parsers/phodevi_windows_parser.php0000644000175000017500000000441511564533734030434 0ustar michaelmichael. */ class phodevi_windows_parser { public static function read_cpuz($section, $name, $match_multiple = false) { $return = $match_multiple ? array() : false; if(is_executable('C:\Program Files\CPUID\CPU-Z\cpuz.exe')) { static $cpuz_log = null; if($cpuz_log == null) { shell_exec('\'C:\Program Files\CPUID\CPU-Z\cpuz.exe\' -txt=' . PTS_USER_PATH . 'cpuz'); if(is_file(PTS_USER_PATH . 'cpuz.txt')) { $cpuz_log = file_get_contents(PTS_USER_PATH . 'cpuz.txt'); unlink(PTS_USER_PATH . 'cpuz.txt'); } } $s = 0; while(($match_multiple || $s == 0) && isset($cpuz_log[($s + 1)]) && ($s = strpos($cpuz_log, "\n" . $section, ($s + 1))) !== false) { $cpuz_section = substr($cpuz_log, $s); if(($name != null && ($c = strpos($cpuz_section, ' ' . $name)) !== false) || ($c = 0) == 0) { if($name == null) { $name = $section; } $cpuz_section = substr($cpuz_section, $c, (strpos($cpuz_section, "\r\n", $c) - $c)); $return_match = substr($cpuz_section, strpos($cpuz_section, $name) + strlen($name)); if(($e = strpos($return_match, '(')) !== false) { $return_match = substr($return_match, 0, $e); } $return_match = trim($return_match); if($match_multiple) { array_push($return, $return_match); } else { $return = $return_match; } } } } return $return; } } ?> phoronix-test-suite/pts-core/objects/phodevi/parsers/phodevi_solaris_parser.php0000644000175000017500000000542211564533734030415 0ustar michaelmichael. */ class phodevi_solaris_parser { public static function read_sun_ddu_dmi_info($find_objects, $args = null) { // Read Sun's Device Driver Utility for OpenSolaris $values = array(); if(in_array(phodevi::read_property('system', 'kernel-architecture'), array('i686', 'x86_64'))) { $dmi_info = '/usr/ddu/bin/i386/dmi_info'; } else { $dmi_info = '/usr/ddu/bin/sparc/dmi_info'; } if(is_executable($dmi_info) || is_executable(($dmi_info = '/usr/ddu/bin/dmi_info'))) { $info = shell_exec($dmi_info . ' ' . $args . ' 2>&1'); $lines = explode("\n", $info); $find_objects = pts_arrays::to_array($find_objects); for($i = 0; $i < count($find_objects) && count($values) == 0; $i++) { $objects = pts_strings::comma_explode($find_objects[$i]); $this_section = null; if(count($objects) == 2) { $section = $objects[0]; $object = $objects[1]; } else { $section = null; $object = $objects[0]; } foreach($lines as $line) { $line = pts_strings::colon_explode($line); $line_object = isset($line[0]) ? str_replace(' ', null, $line[0]) : null; $this_value = count($line) > 1 ? $line[1] : null; if(empty($this_value) && !empty($section)) { $this_section = $line_object; } if($line_object == $object && ($this_section == $section || pts_strings::proximity_match($section, $this_section)) && !empty($this_value) && $this_value != 'Unknown') { array_push($values, $this_value); } } } } return $values; } public static function read_hal_property($udi, $key) { $value = false; if(pts_client::executable_in_path('hal-get-property')) { foreach(pts_arrays::to_array($udi) as $udi_check) { $value = trim(shell_exec('hal-get-property --udi ' . $udi_check . ' --key ' . $key . ' 2> /dev/null')); if($value != false) { break; } } } return $value; } } ?> phoronix-test-suite/pts-core/objects/phodevi/parsers/phodevi_osx_parser.php0000644000175000017500000000375111564533734027555 0ustar michaelmichael. */ class phodevi_osx_parser { public static function read_osx_system_profiler($data_type, $object, $multiple_objects = false, $ignore_values = array()) { $value = ($multiple_objects ? array() : false); if(pts_client::executable_in_path('system_profiler')) { $info = trim(shell_exec('system_profiler ' . $data_type . ' 2>&1')); $lines = explode("\n", $info); for($i = 0; $i < count($lines) && ($value == false || $multiple_objects); $i++) { $line = pts_strings::colon_explode($lines[$i]); if(isset($line[0]) == false) { continue; } $line_object = str_replace(' ', null, $line[0]); if(($cut_point = strpos($line_object, '(')) > 0) { $line_object = substr($line_object, 0, $cut_point); } if(strtolower($line_object) == strtolower($object) && isset($line[1])) { $this_value = trim($line[1]); if(!empty($this_value) && !in_array($this_value, $ignore_values)) { if($multiple_objects) { array_push($value, $this_value); } else { $value = $this_value; } } } } } return $value; } } ?> phoronix-test-suite/pts-core/objects/phodevi/parsers/phodevi_linux_parser.php0000644000175000017500000004410612223040153030057 0ustar michaelmichael. */ class phodevi_linux_parser { public static function read_ipmitool_sensor($sensor) { $value = false; $ipmitool = shell_exec('ipmitool sdr list 2>&1'); $hit = stripos($ipmitool, $sensor); if($hit !== false) { $trimmed = substr($ipmitool, ($hit + strlen($sensor))); $trimmed = substr($trimmed, 0, strpos($trimmed, PHP_EOL)); $trimmed = explode('|', $trimmed); if(count($trimmed) == 3) { $value = explode(' ', trim($trimmed[1])); $value = $value[0]; } } return $value; } public static function read_sysfs_node($search, $type = 'NUMERIC', $node_dir_check = null, $find_position = 1) { static $sysfs_file_cache = null; $arg_hash = crc32(serialize(func_get_args())); if(!isset($sysfs_file_cache[$arg_hash])) { $find_count = 0; foreach(pts_file_io::glob($search) as $sysfs_file) { if(is_array($node_dir_check)) { $skip_to_next = false; $sysfs_dir = dirname($sysfs_file) . '/'; foreach($node_dir_check as $node_check => $value_check) { if(!is_file($sysfs_dir . $node_check)) { $skip_to_next = true; break; } else if($value_check !== true) { $value_check_value = pts_file_io::file_get_contents($sysfs_dir . $node_check); foreach(explode(',', $value_check) as $check) { if(isset($check[0]) && $check[0] == '!') { if($value_check_value == substr($check, 1)) { $skip_to_next = true; break; } } else if($value_check_value != $check) { $skip_to_next = true; break; } } } if($skip_to_next) { break; } } if($skip_to_next) { continue; } } $sysfs_value = pts_file_io::file_get_contents($sysfs_file); switch($type) { case 'NUMERIC': if(is_numeric($sysfs_value)) { $sysfs_file_cache[$arg_hash] = $sysfs_file; } break; case 'POSITIVE_NUMERIC': if(is_numeric($sysfs_value) && $sysfs_value > 0) { $sysfs_file_cache[$arg_hash] = $sysfs_file; } break; case 'NOT_EMPTY': if(!empty($sysfs_value)) { $sysfs_file_cache[$arg_hash] = $sysfs_file; } break; case 'NO_CHECK': $sysfs_file_cache[$arg_hash] = $sysfs_file; break; } $find_count++; if($find_count < $find_position) { unset($sysfs_file_cache[$arg_hash]); } if(isset($sysfs_file_cache[$arg_hash])) { break; } } if(!isset($sysfs_file_cache[$arg_hash])) { $sysfs_file_cache[$arg_hash] = false; } } return $sysfs_file_cache[$arg_hash] == false ? -1 : pts_file_io::file_get_contents($sysfs_file_cache[$arg_hash]); } public static function read_dmidecode($type, $sub_type, $object, $find_once = false, $ignore = null) { // Read Linux dmidecode $value = array(); if(is_readable('/dev/mem') && pts_client::executable_in_path('dmidecode')) { $ignore = pts_arrays::to_array($ignore); $dmidecode = shell_exec('dmidecode --type ' . $type . ' 2>&1'); $sub_type = "\n" . $sub_type . "\n"; do { $sub_type_start = strpos($dmidecode, $sub_type); if($sub_type_start !== false) { $dmidecode = substr($dmidecode, ($sub_type_start + strlen($sub_type))); $dmidecode_section = substr($dmidecode, 0, strpos($dmidecode, "\n\n")); $dmidecode = substr($dmidecode, strlen($dmidecode_section)); $dmidecode_elements = explode("\n", $dmidecode_section); $found_in_section = false; for($i = 0; $i < count($dmidecode_elements) && $found_in_section == false; $i++) { $dmidecode_r = pts_strings::colon_explode($dmidecode_elements[$i]); if($dmidecode_r[0] == $object && isset($dmidecode_r[1]) && !in_array($dmidecode_r[1], $ignore)) { array_push($value, $dmidecode_r[1]); $found_in_section = true; } } } } while($sub_type_start !== false && ($find_once == false || $found_in_section == false)); } if(count($value) == 0) { $value = false; } else if($find_once && count($value) == 1) { $value = $value[0]; } return $value; } public static function read_sys_disk_speed($path, $to_read) { $speed = -1; // in MB/s if(is_file($path)) { switch($to_read) { case 'WRITE': $sector = 6; $time = 7; break; case 'READ': $sector = 2; $time = 3; break; default: return $speed; break; } $start_stat = pts_strings::trim_spaces(file_get_contents($path)); usleep(500000); $end_stat = pts_strings::trim_spaces(file_get_contents($path)); $start_stat = explode(' ', $start_stat); $end_stat = explode(' ', $end_stat); $delta_sectors = $end_stat[$sector] - $start_stat[$sector]; $delta_ms_spent = $end_stat[$time] - $start_stat[$time]; // assuming 512 byte sectors $delta_mb = $delta_sectors * 512 / 1048576; $delta_seconds = $delta_ms_spent / 1000; $speed = $delta_seconds != 0 ? $delta_mb / $delta_seconds : 0; } return pts_math::set_precision($speed, 2); } public static function read_sys_dmi($identifier) { $dmi = false; if(is_dir('/sys/class/dmi/id/')) { $ignore_words = phodevi_parser::hardware_values_to_remove(); foreach(pts_arrays::to_array($identifier) as $id) { if(is_readable('/sys/class/dmi/id/' . $id)) { $dmi_file = pts_file_io::file_get_contents('/sys/class/dmi/id/' . $id); if(!empty($dmi_file) && !in_array(strtolower($dmi_file), $ignore_words)) { $dmi = $dmi_file; break; } } } } return $dmi; } public static function read_ati_overdrive($attribute, $adapter = 0) { // Read ATI OverDrive information // OverDrive supported in fglrx 8.52+ drivers $value = false; if(($amdconfig = self::find_amdconfig())) { if($attribute == 'Temperature') { $info = shell_exec($amdconfig . ' --adapter=' . $adapter . ' --od-gettemperature 2>&1'); if(($start = strpos($info, 'Temperature -')) !== false) { $info = substr($info, $start + 14); $value = substr($info, 0, strpos($info, ' C')); } } else if($attribute == 'FanSpeed') { // Right now there is no standardized interface to get the fan speed through besides the pplib command $info = shell_exec($amdconfig . ' --adapter=' . $adapter . ' --pplib-cmd \'get fanspeed 0\' 2>&1'); if(($start = strpos($info, 'Fan Speed:')) !== false) { $info = substr($info, $start + 11); $info = substr($info, 0, strpos($info, '%')); if(is_numeric($info)) { $value = $info; } } } else { $info = shell_exec($amdconfig . ' --adapter=' . $adapter . ' --od-getclocks 2>&1'); if(strpos($info, 'GPU') !== false) { foreach(explode("\n", $info) as $line) { $line_r = pts_strings::colon_explode($line); if(count($line_r) == 2) { $od_option = str_replace(' ', null, $line_r[0]); if($od_option == $attribute) { $od_value = pts_strings::trim_spaces($line_r[1]); $od_value = str_replace(array('%'), null, $od_value); $od_value_r = explode(' ', $od_value); $value = (count($od_value_r) == 1 ? $od_value_r[0] : $od_value_r); } } } } } } return $value; } public static function read_amd_pcsdb($attribute) { // Read AMD's AMDPCSDB, AMD Persistent Configuration Store Database static $try_aticonfig = true; static $is_first_read = true; $ati_info = null; if($try_aticonfig) { if(($amdconfig = self::find_amdconfig())) { $info = shell_exec($amdconfig . ' --get-pcs-key=' . $attribute . ' 2>&1'); if($is_first_read && strpos($info, 'No supported adapters') != false) { $try_aticonfig = false; } else { if(($pos = strpos($info, ':')) > 0 && strpos($info, 'Error') === false) { $ati_info = substr($info, $pos + 2); $ati_info = substr($ati_info, 0, strpos($ati_info, ' ')); } } } else { $try_aticonfig = false; } $is_first_read = false; } if($ati_info == null && is_file('/etc/ati/amdpcsdb')) { // Using aticonfig --get-pcs-key failed, switch to the PTS direct parser of AMDPCSDB $ati_info = phodevi_linux_parser::read_amd_pcsdb_direct_parser($attribute); } return $ati_info; } public static function read_amd_pcsdb_direct_parser($attribute, $find_once = false) { // Read AMD's AMDPCSDB, AMD Persistent Configuration Store Database but using our own internal parser instead of relying upon aticonfig/amdconfig $amdpcsdb_file = null; $last_found_section_count = -1; $this_section_count = 0; $attribute_values = array(); $attribute = pts_strings::comma_explode($attribute); if(count($attribute) == 2) { $attribute_prefix = array_reverse(explode('/', $attribute[0])); $attribute_key = $attribute[1]; $is_in_prefix = false; if(is_file('/etc/ati/amdpcsdb')) { $amdpcsdb_file = explode("\n", file_get_contents('/etc/ati/amdpcsdb')); } for($l = 0; $l < count($amdpcsdb_file) && ($find_once == false || $last_found_section_count == -1); $l++) { $line = trim($amdpcsdb_file[$l]); if(substr($line, 0, 1) == '[' && substr($line, -1) == ']') { // AMDPCSDB Header $prefix_matches = true; $header = array_reverse(explode('/', substr($line, 1, -1))); for($i = 0; $i < count($attribute_prefix) && $i < count($header) && $prefix_matches; $i++) { if($attribute_prefix[$i] != $header[$i] && pts_strings::proximity_match($attribute_prefix[$i], $header[$i]) == false) { $prefix_matches = false; } } if($prefix_matches) { $is_in_prefix = true; $this_section_count++; } else { $is_in_prefix = false; } } else if($is_in_prefix && $this_section_count != $last_found_section_count && count(($key_components = explode('=', $line))) == 2) { // AMDPCSDB Value if($key_components[0] == $attribute_key) { $value_type = substr($key_components[1], 0, 1); $value = substr($key_components[1], 1); switch($value_type) { case 'V': // Value if(is_numeric($value) && strlen($value) < 9) { $value = dechex($value); $value = '0x' . str_repeat(0, 8 - strlen($value)) . strtoupper($value); } break; case 'R': // Raw break; case 'S': // String break; } array_push($attribute_values, $value); $last_found_section_count = $this_section_count; } } } } if(count($attribute_values) == 0) { $attribute_values = null; } else if(count($attribute_values) == 1) { $attribute_values = $attribute_values[0]; } return $attribute_values; } public static function find_amdconfig() { $amdconfig = false; if(($t = pts_client::executable_in_path('aticonfig'))) { $amdconfig = $t; } else if(($t = pts_client::executable_in_path('amdconfig'))) { $amdconfig = $t; } return $amdconfig; } public static function read_amd_graphics_adapters() { // Read ATI/AMD graphics hardware using aticonfig $adapters = array(); if(($amdconfig = self::find_amdconfig())) { $info = trim(shell_exec($amdconfig . ' --list-adapters 2>&1')); foreach(explode("\n", $info) as $line) { if(($last_point = strrpos($line, '.')) > 0) { array_push($adapters, substr($line, $last_point + 3)); } } } return $adapters; } public static function read_cpuinfo($attribute, $cpuinfo = false) { // Read CPU information $cpuinfo_matches = array(); if($cpuinfo == false) { if(is_file('/proc/cpuinfo')) { $cpuinfo = file_get_contents('/proc/cpuinfo'); } else { return $cpuinfo_matches; } } foreach(pts_arrays::to_array($attribute) as $attribute_check) { $cpuinfo_lines = explode("\n", $cpuinfo); foreach($cpuinfo_lines as $line) { $line = pts_strings::trim_explode(': ', $line); if(!isset($line[0])) { continue; } $this_attribute = $line[0]; $this_value = (count($line) > 1 ? $line[1] : null); if($this_attribute == $attribute_check) { array_push($cpuinfo_matches, $this_value); } } if(count($cpuinfo_matches) != 0) { break; } } return $cpuinfo_matches; } public static function read_lsb_distributor_id() { $vendor = phodevi_linux_parser::read_lsb('Distributor ID'); // Quirks for derivative distributions that don't know how to handle themselves properly if($vendor == 'MandrivaLinux' && phodevi_linux_parser::read_lsb('Description') == 'PCLinuxOS') { // PC Linux OS only stores its info in /etc/pclinuxos-release $vendor = false; } return $vendor; } public static function read_lsb($desc) { // Read LSB Release information, Linux Standards Base $info = false; if(pts_client::executable_in_path('lsb_release')) { static $output = null; if($output == null) { $output = shell_exec('lsb_release -a 2>&1'); } if(($pos = strrpos($output, $desc . ':')) !== false) { $info = substr($output, $pos + strlen($desc) + 1); $info = trim(substr($info, 0, strpos($info, "\n"))); } if(strtolower($info) == 'n/a') { $info = false; } } return $info; } public static function read_acpi($point, $match) { // Read ACPI - Advanced Configuration and Power Interface $value = false; $point = pts_arrays::to_array($point); for($i = 0; $i < count($point) && empty($value); $i++) { if(is_file('/proc/acpi' . $point[$i])) { $acpi_lines = explode("\n", file_get_contents('/proc/acpi' . $point[$i])); for($i = 0; $i < count($acpi_lines) && $value == false; $i++) { $line = pts_strings::trim_explode(': ', $acpi_lines[$i]); if(!isset($line[0])) { continue; } $this_attribute = $line[0]; $this_value = (count($line) > 1 ? $line[1] : null); if($this_attribute == $match) { $value = $this_value; } } } } return $value; } public static function read_pci_subsystem_value($desc) { $lspci = shell_exec('lspci -v 2> /dev/null'); $subsystem = null; foreach(pts_arrays::to_array($desc) as $check) { if(($hit = strpos($lspci, $check)) !== false) { $lspci = substr($lspci, $hit); if(($hit = strpos($lspci, 'Subsystem: ')) !== false) { $lspci = substr($lspci, ($hit + strlen('Subsystem: '))); $lspci = substr($lspci, 0, strpos($lspci, PHP_EOL)); $vendors = array( 'Sapphire Technology' => 'Sapphire', 'PC Partner' => 'Sapphire', 'Micro-Star International' => 'MSI', 'XFX' => 'XFX', 'ASUS' => 'ASUS', 'Gigabyte' => 'Gigabyte', 'Elitegroup' => 'ECS', 'eVga' => 'eVGA', ); foreach($vendors as $vendor => $clean_vendor) { if(stripos($lspci, $vendor) !== false) { $subsystem = $clean_vendor; break; } } } } } return $subsystem; } public static function read_pci($desc, $clean_string = true) { // Read PCI bus information static $pci_info = null; $info = false; $desc = pts_arrays::to_array($desc); if($pci_info == null) { if(!is_executable('/usr/bin/lspci') && is_executable('/sbin/lspci')) { $lspci_cmd = '/sbin/lspci'; } else if(($lspci = pts_client::executable_in_path('lspci'))) { $lspci_cmd = $lspci; } else { return false; } $pci_info = shell_exec($lspci_cmd . ' 2> /dev/null'); } for($i = 0; $i < count($desc) && empty($info); $i++) { if(substr($desc[$i], -1) != ':') { $desc[$i] .= ':'; } if(($pos = strpos($pci_info, $desc[$i])) !== false) { $sub_pci_info = str_replace(array('[AMD]', '[AMD/ATI]'), null, substr($pci_info, $pos + strlen($desc[$i]))); $EOL = strpos($sub_pci_info, "\n"); if($clean_string) { if(($temp = strpos($sub_pci_info, '/')) < $EOL && $temp > 0) { if(($temp = strpos($sub_pci_info, ' ', ($temp + 2))) < $EOL && $temp > 0) { $EOL = $temp; } } if(($temp = strpos($sub_pci_info, '(')) < $EOL && $temp > 0) { $EOL = $temp; } if(($temp = strpos($sub_pci_info, '[')) < $EOL && $temp > 0) { $EOL = $temp; } } $sub_pci_info = trim(substr($sub_pci_info, 0, $EOL)); if(($strlen = strlen($sub_pci_info)) >= 6 && $strlen < 128) { $info = pts_strings::strip_string($sub_pci_info); } } } return $info; } public static function read_sensors($attributes) { // Read LM_Sensors $value = false; if(isset(phodevi::$vfs->sensors)) { $sensors = phodevi::$vfs->sensors; $sensors_lines = explode("\n", $sensors); $attributes = pts_arrays::to_array($attributes); for($j = 0; $j < count($attributes) && empty($value); $j++) { $attribute = $attributes[$j]; for($i = 0; $i < count($sensors_lines) && $value == false; $i++) { $line = pts_strings::trim_explode(': ', $sensors_lines[$i]); if(!isset($line[0])) { continue; } $this_attribute = $line[0]; if($this_attribute == $attribute) { $this_remainder = trim(str_replace(array('+', '°'), ' ', $line[1])); $this_value = substr($this_remainder, 0, strpos($this_remainder, ' ')); if(is_numeric($this_value) && $this_value > 0) { $value = $this_value; } } } } } return $value; } } ?> phoronix-test-suite/pts-core/objects/client/display_modes/pts_display_mode_interface.php0000644000175000017500000000457111751501052032211 0ustar michaelmichael. */ interface pts_display_mode_interface { public function __construct(); public function test_install_process($test_install_manager); public function test_install_begin($test_install_request); public function test_install_downloads($test_install_request); public function test_install_download_file($process, &$pts_test_file_download); public function test_install_progress_start($process); public function test_install_progress_update($progress_float); public function test_install_progress_completed(); public function test_run_process_start(&$test_run_manager); public function test_install_start($test_identifier); public function test_install_output(&$to_output); public function test_install_error($error_string); public function test_install_prompt($prompt_string); public function test_run_configure(&$test_profile); public function test_run_start(&$test_run_manager, &$test_result); public function test_run_message($message_string); public function test_run_instance_header(&$test_result); public function test_run_instance_error($error_string); public function test_run_instance_output(&$to_output); public function test_run_instance_complete(&$test_result); public function test_run_end(&$test_result); public function test_run_error($error_string); public function generic_prompt($prompt_string); public function generic_heading($string); public function generic_sub_heading($string); public function generic_error($string); public function generic_warning($string); public function get_tab(); } ?> phoronix-test-suite/pts-core/objects/client/display_modes/pts_basic_display_mode.php0000644000175000017500000001456511751501156031343 0ustar michaelmichael. */ class pts_basic_display_mode implements pts_display_mode_interface { // Run bits private $expected_trial_run_count = 0; private $trial_run_count_current = 0; public function __construct() { } public function test_install_process($test_install_manager) { return; } public function test_install_begin($test_install_request) { return; } public function test_install_downloads($test_install_request) { echo self::string_header('Downloading Files: ' . $test_install_request->test_profile->get_identifier()); } public function test_install_download_file($process, &$pts_test_file_download) { switch($process) { case 'DOWNLOAD_FROM_CACHE': echo 'Downloading Cached File: ' . $pts_test_file_download->get_filename() . PHP_EOL . PHP_EOL; break; case 'LINK_FROM_CACHE': echo 'Linking Cached File: ' . $pts_test_file_download->get_filename() . PHP_EOL; break; case 'COPY_FROM_CACHE': echo 'Copying Cached File: ' . $pts_test_file_download->get_filename() . PHP_EOL; break; case 'DOWNLOAD': echo PHP_EOL . PHP_EOL . 'Downloading File: ' . $pts_test_file_download->get_filename() . PHP_EOL . PHP_EOL; break; case 'FILE_FOUND': break; } } public function test_install_progress_start($process) { return; } public function test_install_progress_update($download_float) { return; } public function test_install_progress_completed() { return; } public function test_install_start($identifier) { echo self::string_header('Installing Test: ' . $identifier); } public function test_install_output(&$to_output) { if(!isset($to_output[10240]) || (pts_c::$test_flags & pts_c::debug_mode)) { // Not worth printing files over 10kb to screen echo $to_output; } } public function test_install_error($error_string) { echo PHP_EOL . $error_string . PHP_EOL; } public function test_install_prompt($prompt_string) { echo PHP_EOL . $prompt_string; } public function test_run_process_start(&$test_run_manager) { return; } public function test_run_message($message_string) { echo PHP_EOL . $message_string . PHP_EOL; } public function test_run_start(&$test_run_manager, &$test_result) { $this->trial_run_count_current = 0; $this->expected_trial_run_count = $test_result->test_profile->get_times_to_run(); } public function test_run_instance_header(&$test_result) { $this->trial_run_count_current++; echo self::string_header($test_result->test_profile->get_title() . ' (Run ' . $this->trial_run_count_current . ' of ' . $this->expected_trial_run_count . ')'); } public function test_run_instance_output(&$to_output) { echo $to_output; } public function test_run_instance_complete(&$test_result) { // Do nothing here } public function test_run_end(&$test_result) { $end_print = $test_result->test_profile->get_title() . ':' . PHP_EOL . $test_result->get_arguments_description(); $end_print .= PHP_EOL . ($test_result->get_arguments_description() != null ? PHP_EOL : null); if(in_array($test_result->test_profile->get_display_format(), array('NO_RESULT', 'FILLED_LINE_GRAPH', 'LINE_GRAPH', 'IMAGE_COMPARISON'))) { return; } else if(in_array($test_result->test_profile->get_display_format(), array('PASS_FAIL', 'MULTI_PASS_FAIL'))) { $end_print .= PHP_EOL . 'Final: ' . $test_result->get_result() . ' (' . $test_result->test_profile->get_result_scale() . ')' . PHP_EOL; } else { foreach($test_result->test_result_buffer->get_values() as $result) { $end_print .= $result . ' ' . $test_result->test_profile->get_result_scale() . PHP_EOL; } $end_print .= PHP_EOL . pts_strings::result_quantifier_to_string($test_result->test_profile->get_result_quantifier()) . ': ' . $test_result->get_result() . ' ' . $test_result->test_profile->get_result_scale(); } echo self::string_header($end_print, '#'); } public function test_run_error($error_string) { echo PHP_EOL . $error_string . PHP_EOL . PHP_EOL; } public function test_run_instance_error($error_string) { echo PHP_EOL . $error_string . PHP_EOL . PHP_EOL; } public function generic_prompt($prompt_string) { echo PHP_EOL . $prompt_string; } public function generic_heading($string) { static $shown_pts = false; if($shown_pts == false) { $string = pts_title() . PHP_EOL . $string; } echo self::string_header($string, '='); } public function generic_sub_heading($string) { echo $string . PHP_EOL; } public function generic_error($string) { echo self::string_header($string, '='); } public function generic_warning($string) { echo self::string_header($string, '='); } protected static function string_header($heading, $char = '=') { // Return a string header if(!isset($heading[1])) { return null; } $header_size = 40; foreach(explode(PHP_EOL, $heading) as $line) { if(isset($line[($header_size + 1)])) // Line to write is longer than header size { $header_size = strlen($line); } } if(($terminal_width = pts_client::terminal_width()) < $header_size && $terminal_width > 0) { $header_size = $terminal_width; } return PHP_EOL . str_repeat($char, $header_size) . PHP_EOL . $heading . PHP_EOL . str_repeat($char, $header_size) . PHP_EOL . PHP_EOL; } public function test_run_configure(&$test_profile) { echo PHP_EOL . PHP_EOL . $test_profile->get_title() . ($test_profile->get_app_version() != null ? ' ' . $test_profile->get_app_version() : null) . ':' . PHP_EOL . $test_profile->get_identifier() . PHP_EOL; echo $test_profile->get_test_hardware_type() . ' Test Configuration'; } public function get_tab() { return null; } } ?> phoronix-test-suite/pts-core/objects/client/display_modes/pts_concise_display_mode.php0000644000175000017500000003634412166053272031706 0ustar michaelmichael. */ class pts_concise_display_mode implements pts_display_mode_interface { private $tab = ' '; // Download / progress bits private $progress_tab_count = 1; private $progress_line_prefix = null; private $progress_char_count = 0; private $progress_char_pos = 0; private $progress_string_length = 0; private $progress_last_float = -1; // Test install bits private $test_install_pos = 0; private $test_install_count = 0; // Run bits private $expected_trial_run_count = 0; private $trial_run_count_current = 0; public function __construct() { } protected function bytes_to_download_size($bytes) { $mb = pts_math::set_precision($bytes / 1048576, 2); if($mb > 99) { $mb = ceil($mb); } return $mb; } public function test_install_process($test_install_manager) { $this->test_install_pos = 0; $this->test_install_count = $test_install_manager->tests_to_install_count(); echo PHP_EOL; echo $this->tab . $this->test_install_count . ' Test' . ($this->test_install_count > 1 ? 's' : null) . ' To Install' . PHP_EOL; $download_size = 0; $download_total = 0; $cache_total = 0; $cache_size = 0; $install_size = 0; foreach($test_install_manager->get_test_run_requests() as $test_run_request) { $install_size += $test_run_request->test_profile->get_environment_size(); foreach($test_run_request->get_download_objects() as $test_file_download) { switch($test_file_download->get_download_location_type()) { case 'IN_DESTINATION_DIR': // We don't really care about these files here since they are good to go break; case 'LOCAL_DOWNLOAD_CACHE': case 'REMOTE_DOWNLOAD_CACHE': case 'LOOKASIDE_DOWNLOAD_CACHE': $cache_size += $test_file_download->get_filesize(); $cache_total++; break; default: $download_size += $test_file_download->get_filesize(); $download_total++; break; } } } if($download_total > 0) { echo $this->tab . $this->tab . $download_total . ' File' . ($download_total > 1 ? 's' : null) . ' To Download'; if($download_size > 0) { echo ' [' . self::bytes_to_download_size($download_size) . 'MB]'; } echo PHP_EOL; } if($cache_total > 0) { echo $this->tab . $this->tab . $cache_total . ' File' . ($cache_total > 1 ? 's' : null) . ' In Cache'; if($cache_size > 0) { echo ' [' . self::bytes_to_download_size($cache_size) . 'MB]'; } echo PHP_EOL; } if($install_size > 0) { echo $this->tab . $this->tab . ceil($install_size) . 'MB Of Disk Space Is Needed' . PHP_EOL; } echo PHP_EOL; } public function test_install_start($identifier) { $this->test_install_pos++; echo $this->tab . $identifier . ':' . PHP_EOL; echo $this->tab . $this->tab . 'Test Installation ' . $this->test_install_pos . ' of ' . $this->test_install_count . PHP_EOL; } public function test_install_downloads($test_install_request) { $identifier = $test_install_request->test_profile->get_identifier(); $download_packages = $test_install_request->get_download_objects(); echo $this->tab . $this->tab . count($download_packages) . ' File' . (isset($download_packages[1]) ? 's' : null) . ' Needed'; if(($size = $test_install_request->test_profile->get_download_size(false, 1048576)) > 0) { if($size > 99) { $size = ceil($size); } echo ' [' . $size . ' MB'; if(($avg_speed = pts_download_speed_manager::get_average_download_speed()) > 0) { $avg_time = ($size * 1048576) / $avg_speed; echo ' / ' . pts_strings::format_time($avg_time, 'SECONDS', true, 60); } echo ']'; } echo PHP_EOL; } public function test_install_download_file($process, &$pts_test_file_download) { $expected_time = 0; $progress_prefix = null; switch($process) { case 'DOWNLOAD_FROM_CACHE': $process_string = 'Downloading From Cache'; $progress_prefix = 'Downloading'; break; case 'LINK_FROM_CACHE': $process_string = 'Linking From Cache'; break; case 'COPY_FROM_CACHE': $process_string = 'Copying From Cache'; $progress_prefix = 'Copying'; break; case 'FILE_FOUND': $process_string = 'File Found'; break; case 'DOWNLOAD': $process_string = 'Downloading'; $progress_prefix = 'Downloading'; if(($avg_speed = pts_download_speed_manager::get_average_download_speed()) > 0 && ($this_size = $pts_test_file_download->get_filesize()) > 0) { $expected_time = $this_size / $avg_speed; } break; } $expected_time = is_numeric($expected_time) && $expected_time > 0 ? pts_strings::format_time($expected_time, 'SECONDS', false, 60) : null; // TODO: handle if file-name is too long for terminal width $download_string = $this->tab . $this->tab . $process_string . ': ' . $pts_test_file_download->get_filename(); $download_size_string = $pts_test_file_download->get_filesize() > 0 ? ' [' . self::bytes_to_download_size($pts_test_file_download->get_filesize()) . 'MB]' : null; $offset_length = pts_client::terminal_width() > 1 ? pts_client::terminal_width() : pts_test_file_download::$longest_file_name_length; $offset_length = $offset_length - strlen($download_string) - strlen($download_size_string) - 2; if($offset_length < 2) { $offset_length = 2; } $download_string .= str_repeat(' ', ($offset_length - 2)); $download_string .= $download_size_string; echo $download_string . PHP_EOL; $this->progress_line_prefix = $expected_time != null ? 'Estimated Download Time: ' . $expected_time : $progress_prefix; $this->progress_last_float = -1; $this->progress_tab_count = 2; $this->progress_string_length = strlen($download_string); } public function test_install_progress_start($process) { $this->progress_line_prefix = $process; $this->progress_last_float = -1; $this->progress_tab_count = 1; $this->progress_string_length = pts_client::terminal_width() > 1 ? pts_client::terminal_width() - 4 : 20; return; } public function test_install_progress_update($progress_float) { if($this->progress_last_float == -1) { $progress_prefix = str_repeat($this->tab, $this->progress_tab_count) . $this->progress_line_prefix . ' '; echo $progress_prefix; $this->progress_char_count = $this->progress_string_length - strlen($progress_prefix); $this->progress_char_pos = 0; } $char_current = floor($progress_float * $this->progress_char_count); if($char_current > $this->progress_char_pos && $char_current <= $this->progress_char_count) { echo str_repeat('.', $char_current - $this->progress_char_pos); $this->progress_char_pos = $char_current; } $this->progress_last_float = $progress_float; } public function test_install_progress_completed() { echo $this->progress_last_float != -1 ? str_repeat('.', $this->progress_char_count - $this->progress_char_pos) . PHP_EOL : null; $this->progress_last_float == -1; } public function test_install_begin($test_install_request) { if(($size = $test_install_request->test_profile->get_environment_size(false)) > 0) { echo $this->tab . $this->tab . 'Installation Size: ' . $size . ' MB' . PHP_EOL; } echo $this->tab . $this->tab . 'Installing Test' . ' @ ' . date('H:i:s') . PHP_EOL; return; } public function test_install_output(&$to_output) { return; } public function test_install_error($error_string) { echo $this->tab . $this->tab . $this->tab . $error_string . PHP_EOL; } public function test_install_prompt($prompt_string) { echo $this->tab . $this->tab . $this->tab . $prompt_string; } public function test_run_process_start(&$test_run_manager) { return; } public function test_run_configure(&$test_profile) { echo PHP_EOL . PHP_EOL . $test_profile->get_title() . ($test_profile->get_app_version() != null ? ' ' . $test_profile->get_app_version() : null) . ':' . PHP_EOL . $this->tab . $test_profile->get_identifier() . PHP_EOL; echo $this->tab . $test_profile->get_test_hardware_type() . ' Test Configuration'; //echo PHP_EOL; //echo $this->tab . 'Test ' . $test_run_manager->get_test_run_position() . ' of ' . $test_run_manager->get_test_run_count_reported() . PHP_EOL; } public function test_run_start(&$test_run_manager, &$test_result) { echo PHP_EOL . PHP_EOL . $test_result->test_profile->get_title() . ($test_result->test_profile->get_app_version() != null ? ' ' . $test_result->test_profile->get_app_version() : null) . ':' . PHP_EOL . $this->tab . $test_result->test_profile->get_identifier(); if(($test_description = $test_result->get_arguments_description()) != false) { echo ' [' . pts_client::swap_variables($test_description, array('pts_client', 'environmental_variables')) . ']'; } echo PHP_EOL; echo $this->tab . 'Test ' . $test_run_manager->get_test_run_position() . ' of ' . $test_run_manager->get_test_run_count_reported() . PHP_EOL; $this->trial_run_count_current = 0; $this->expected_trial_run_count = $test_result->test_profile->get_times_to_run(); $remaining_length = $test_run_manager->get_estimated_run_time(); $estimated_length = $test_result->test_profile->get_estimated_run_time(); $display_table = array(); array_push($display_table, array($this->tab . 'Estimated Trial Run Count:', $this->expected_trial_run_count)); if($estimated_length > 1 && $estimated_length != $remaining_length) { array_push($display_table, array($this->tab . 'Estimated Test Run-Time:', pts_strings::format_time($estimated_length, 'SECONDS', true, 60))); } if($remaining_length > 1) { array_push($display_table, array($this->tab . 'Estimated Time To Completion:', pts_strings::format_time($remaining_length, 'SECONDS', true, 60))); } echo pts_user_io::display_text_table($display_table); } public function test_run_message($message_string) { echo PHP_EOL . $this->tab . $this->tab . $message_string . ' @ ' . date('H:i:s'); } public function test_run_instance_header(&$test_result) { $this->trial_run_count_current++; echo PHP_EOL . $this->tab . $this->tab . 'Started Run ' . $this->trial_run_count_current . ' @ ' . date('H:i:s'); } public function test_run_instance_error($error_string) { echo PHP_EOL . $this->tab . $this->tab . $error_string; } public function test_run_instance_output(&$to_output) { if((pts_c::$test_flags & pts_c::debug_mode)) { echo $to_output; } return; } public function test_run_instance_complete(&$test_result) { if($this->expected_trial_run_count > 1 && $this->trial_run_count_current >= $this->expected_trial_run_count) { $values = $test_result->test_result_buffer->get_values(); if(count($values) > 1) { echo ($this->trial_run_count_current < 10 ? ' ' : null) . ' [Std. Dev: ' . pts_math::set_precision(pts_math::percent_standard_deviation($values), 2) . '%]'; } } } public function test_run_end(&$test_result) { echo PHP_EOL; if(in_array($test_result->test_profile->get_display_format(), array('NO_RESULT', 'IMAGE_COMPARISON'))) { $end_print = null; } else if(in_array($test_result->test_profile->get_display_format(), array('PASS_FAIL', 'MULTI_PASS_FAIL'))) { $end_print = $this->tab . $this->tab . 'Final: ' . $test_result->get_result() . ' (' . $test_result->test_profile->get_result_scale() . ')' . PHP_EOL; } else if(in_array($test_result->test_profile->get_display_format(), array('FILLED_LINE_GRAPH', 'LINE_GRAPH'))) { $values = explode(',', $test_result->get_result()); $end_print = null; if(count($values) > 1) { $avg = pts_math::set_precision(array_sum($values) / count($values), 2); $min = pts_math::set_precision(min($values), 2); $max = pts_math::set_precision(max($values), 2); $end_print .= $this->tab . $this->tab . 'Average: ' . $avg . ' (' . $test_result->test_profile->get_result_scale() . ')' . PHP_EOL; $end_print .= $this->tab . $this->tab . 'Minimum: ' . $min . ' (' . $test_result->test_profile->get_result_scale() . ')' . PHP_EOL; $end_print .= $this->tab . $this->tab . 'Maximum: ' . $max . ' (' . $test_result->test_profile->get_result_scale() . ')' . PHP_EOL; } } else { $end_print = PHP_EOL . $this->tab . 'Test Results:' . PHP_EOL; foreach($test_result->test_result_buffer->get_values() as $result) { $end_print .= $this->tab . $this->tab . $result . PHP_EOL; } $end_print .= PHP_EOL . $this->tab . pts_strings::result_quantifier_to_string($test_result->test_profile->get_result_quantifier()) . ': ' . $test_result->get_result() . ' ' . $test_result->test_profile->get_result_scale(); if($test_result->get_min_result()) { $end_print .= PHP_EOL . $this->tab . 'Minimum: ' . $test_result->get_min_result(); } if($test_result->get_max_result()) { $end_print .= PHP_EOL . $this->tab . 'Maximum: ' . $test_result->get_max_result(); } if($test_result->get_result() == 0) { $end_print .= PHP_EOL . $this->tab . 'This test failed to run properly.'; } $end_print .= PHP_EOL; } echo $end_print; } public function test_run_error($error_string) { echo $this->tab . $this->tab . $error_string . PHP_EOL; } public function generic_prompt($prompt_string) { echo $this->tab . $prompt_string; } public function generic_heading($string, $ending_line_break = true) { static $shown_pts = false; if($shown_pts == false) { $string = pts_title() . PHP_EOL . $string; $shown_pts = true; } if(!empty($string)) { echo PHP_EOL; foreach(pts_strings::trim_explode(PHP_EOL, $string) as $line_count => $line_string) { // ($line_count > 0 ? $this->tab : null) . echo $line_string . PHP_EOL; } if($ending_line_break) { echo PHP_EOL; } } } public function generic_sub_heading($string) { if(!empty($string)) { // To generate the 'Phoronix Test Suite' heading string if not already done so pts_client::$display->generic_heading(null, false); foreach(pts_strings::trim_explode(PHP_EOL, $string) as $line_string) { echo $this->tab . $line_string . PHP_EOL; } } } public function generic_error($string) { echo PHP_EOL; echo 'ERROR: '; foreach(pts_strings::trim_explode(PHP_EOL, $string) as $line_count => $line_string) { // ($line_count > 0 ? $this->tab : null) . echo ($line_count > 0 ? ' ' : null) . $line_string . PHP_EOL; } echo PHP_EOL; } public function generic_warning($string) { echo PHP_EOL; echo 'WARNING: '; foreach(pts_strings::trim_explode(PHP_EOL, $string) as $line_count => $line_string) { // ($line_count > 0 ? $this->tab : null) . echo ($line_count > 0 ? ' ' : null) . $line_string . PHP_EOL; } echo PHP_EOL; } public function get_tab() { return $this->tab; } } ?> phoronix-test-suite/pts-core/openbenchmarking.org/schemas/test-profile-downloads.xsd0000644000175000017500000000253112172340012031213 0ustar michaelmichael Phoronix Test Suite / OpenBenchmarking.org XML Test Profile Specification Copyright (C) 2008 - 2013, Phoronix Media Copyright (C) 2008 - 2013, Michael Larabel phoronix-test-suite/pts-core/openbenchmarking.org/schemas/types.xsd0000644000175000017500000001233712100007000025743 0ustar michaelmichael Phoronix Test Suite / OpenBenchmarking.org Copyright (C) 2008 - 2013, Phoronix Media Copyright (C) 2008 - 2013, Michael Larabel phoronix-test-suite/pts-core/openbenchmarking.org/schemas/test-suite.xsd0000644000175000017500000000357011564533734026743 0ustar michaelmichael Phoronix Test Suite / OpenBenchmarking.org XML Result File Specification Copyright (C) 2008 - 2010, Phoronix Media Copyright (C) 2008 - 2010, Michael Larabel phoronix-test-suite/pts-core/openbenchmarking.org/schemas/result-file.xsd0000644000175000017500000000556511725432513027066 0ustar michaelmichael Phoronix Test Suite / OpenBenchmarking.org XML Result File Specification Copyright (C) 2008 - 2012, Phoronix Media Copyright (C) 2008 - 2012, Michael Larabel phoronix-test-suite/pts-core/openbenchmarking.org/schemas/results-parser.xsd0000644000175000017500000000561512171654651027627 0ustar michaelmichael Phoronix Test Suite / OpenBenchmarking.org XML Test Profile Specification Copyright (C) 2008 - 2013, Phoronix Media Copyright (C) 2008 - 2013, Michael Larabel phoronix-test-suite/pts-core/openbenchmarking.org/schemas/test-profile.xsd0000644000175000017500000001257712171652010027241 0ustar michaelmichael Phoronix Test Suite / OpenBenchmarking.org XML Test Profile Specification Copyright (C) 2008 - 2013, Phoronix Media Copyright (C) 2008 - 2013, Michael Larabel phoronix-test-suite/pts-core/external-test-dependencies/xml/arch-packages.xml0000644000175000017500000001142612135352146027616 0ustar michaelmichael Arch Linux pacman gtk-development gtk2 sdl-development sdl sdl_net sdl_gfx sdl_image sdl_ttf glut freeglut libpng-development libpng build-utilities gcc g++ xorg-development xorg openssl-development openssl bison bison flex flex imlib2-development imlib2 java openjdk6 portaudio-development portaudio fortran-compiler gcc-fortran glew glew scons scons zlib-development zlib1 jpeg-development libjpeg perl perl /usr/bin/perl xorg-video xorg libstdcpp5 libstdc++5 openal-development openal vorbis-development libvorbis jam ftjam qt4-development qt4 autoconf autoconf /usr/bin/autoconf libtool libtool numa-development numactl curl curl fftw3-development fftw blas-development blas lapack-development lapack cmake cmake boost-development boost p7zip p7zip cairo-development cairo tcl tcl python python yasm yasm lib3ds lib3ds gmp-library libgmp subversion subversion git git superlu superlu phoronix-test-suite/pts-core/external-test-dependencies/xml/opensuse-packages.xml0000644000175000017500000001414312120152020030520 0ustar michaelmichael OpenSuSE SUSE Linux, SUSE zypper gtk-development gtk2-devel sdl-development libSDL-devel libSDL_image-devel libSDL_gfx-devel libSDL_net-devel libSDL_ttf-devel glut freeglut-devel openssl-development libopenssl-devel csh tcsh libpng-development libpng-devel build-utilities gcc gcc-c++ make autoconf gcc, g++, make, autoconf xorg-development xorg-x11-server-sdk cairo-development cairo-devel p7zip p7zip bison bison flex flex imlib2-development imlib2-devel java java-1_6_0-openjdk /usr/lib/jvm/ OR /usr/lib64/jvm/ portaudio-development portaudio-devel fortran-compiler gcc-fortran glew glew-devel freeimage libfreeimage3 libfreeimage-devel scons scons zlib-development zlib-devel jpeg-development libjpeg-devel libaio-development libaio-devel perl perl xorg-video xorg-x11-libXv-devel xorg-x11-devel libstdcpp5 libstdc++5 openal-development libopenal-devel libopenal0-soft vorbis-development taglib-devel jam boost-jam asio-devel qt4-development libqt4-devel autoconf autoconf libtool libtool ncurses-development libncurses5-devel popt popt-devel numa-development libnuma-devel curl curl fftw3-development fftw3-devel blas-development blas-devel lapack-development lapack-devel cmake cmake boost-development boost-devel bzip2-development libbz2-devel tcl tcl glibc-development glibc-devel glibc-devel-32bit python python atlas-development libatlas3-devel openmpi-development openmpi yasm yasm lib3ds lib3ds-devel gmp-library libgmp3 subversion subversion git git-core superlu superlu phoronix-test-suite/pts-core/external-test-dependencies/xml/dragonfly-packages.xml0000664000175000017500000001642212145043102030657 0ustar michaelmichael DragonFlyBSD common-dependencies archivers/unzip unzip gtk-development x11/gtk2 /usr/pkg/include/gtk-2.0/ sdl-development devel/SDL devel/SDL_gfx devel/SDL_image /usr/pkg/include/SDL/SDL.h, /usr/pkg/include/SDL/SDL_image.h libpng-development graphics/png /usr/pkg/include/png.h openssl-development security/openssl /usr/pkg/include/openssl/ssl.h build-utilities devel/autoconf /usr/pkg/bin/autoconf cairo-development graphics/cairo /usr/pkg/include/cairo/cairo.h bison devel/bison /usr/pkg/bin/bison imlib2-development graphics/imlib2 /usr/pkg/lib/imlib2/ portaudio-development audio/portaudio /usr/pkg/include/portaudio.h fortran-compiler lang/g95 /usr/pkg/bin/g95 glew graphics/glew /usr/pkg/include/GL/glew.h lib3ds graphics/lib3ds /usr/pkg/include/lib3ds/io.h scons devel/scons /usr/pkg/bin/scons jpeg-development graphics/jpeg /usr/pkg/include/jpeglib.h perl lang/perl5 /usr/pkg/bin/perl openal-development audio/openal /usr/pkg/include/AL/al.h vorbis-development audio/libvorbis /usr/pkg/include/vorbis/vorbisfile.h jam devel/jam /usr/pkg/bin/jam p7zip archivers/p7zip /usr/pkg/bin/7za qt4-development x11/qt4 /usr/pkg/include/qt4/Qt/qgl.h autoconf devel/autoconf /usr/pkg/bin/autoconf libtool devel/libtool /usr/pkg/bin/libtool ncurses-development devel/ncurses /usr/pkg/include/ncurses/ncurses.h popt devel/popt /usr/pkg/include/popt.h fftw3-development math/fftw /usr/pkg/include/fftw3.h blas-development math/blas /usr/pkg/lib/libblas.so lapack-development math/lapack /usr/pkg/lib/liblapack.so cmake devel/cmake /usr/pkg/bin/cmake boost-development devel/boost-build devel/boost-headers devel/boost-libs /usr/pkg/include/boost/iostreams/write.hpp bzip2-development archivers/bzip2 /usr/pkg/include/bzlib.h tcl devel/tcllib /usr/pkg/bin/tclsh8.5 python lang/python33 /usr/pkg/bin/python python-boost-development devel/boost-python /usr/pkg/include/boost/python.hpp yasm devel/yasm /usr/pkg/bin/yasm gmp-library math/fgmp /usr/pkg/include/gmp.h subversion devel/subversion /usr/pkg/bin/svn superlu math/superlu /usr/pkg/include/superlu/ glut graphics/glut /usr/pkg/include/GL/glut.h csh shells/tcsh /usr/local/bin/tcsh flex devel/flex /usr/pkg/bin/flex curl www/curl /usr/pkg/bin/curl openmpi-development parallel/openmpi parallel/mpi-ch /usr/pkg/mpi/openmpi/lib, /usr/pkg/include/mpicxx.h git misc/git /usr/pkg/bin/git phoronix-test-suite/pts-core/external-test-dependencies/xml/angstrom-packages.xml0000644000175000017500000001053012106522453030524 0ustar michaelmichael Angstrom gtk-development gtk+-dev sdl-development libsdl-1.2-dev libsdl-image-1.2-dev libsdl-ttf-dev libsdl-x11-dev libsdl-net-1.2-dev libsdl-gfx-dev glut freeglut-dev libpng-development libpng-dev build-utilities cpp gcc autoconf automake libstdc++-dev cpp xorg-development xserver-xorg-dev bison bison flex flex imlib2-development libimlib2-dev java openjdk-6-jdk portaudio-development libportaudio-dev fortran-compiler gfortran freeimage libfreeimage3 scons python-scons /usr/bin/scons zlib-development python-zlib jpeg-development libjpeg-dev perl perl sdl-perl xorg-video libxvmc-dev libxv-dev vorbis-development libvorbis-dev qt4-development libqtcore4-dev autoconf autoconf libtool libtool ncurses-development ncurses-dev popt libpopt-dev curl curl libcurl4 libcurl5 fftw3-development fftw-dev libfftw cmake cmake boost-development boost-dev bzip2-development bzip2-dev tcl tcl glibc-development libc6-dev python python python-boost-development boost-python libboost-python1.33.1 boost-thread-development boost-thread libboost-thread-mt1.33.1 python-numpy python-numpy gmp-library libgmp-dev phoronix-test-suite/pts-core/external-test-dependencies/xml/netbsd-packages.xml0000644000175000017500000001076312102077533030161 0ustar michaelmichael NetBSD 32bit-compatibility suse_base suse32_base /usr/pkg/emul/linux/bin/bash gtk-development gtk2+ /usr/pkg/include/gtk-2.0 sdl-development SDL SDL_net SDL_image /usr/pkg/include/SDL/SDL.h, /usr/pkg/include/SDL/SDL_net.h, /usr/pkg/include/SDL/SDL_image.h glut glut /usr/pkg/lib/libglut.la, /usr/pkg/include/GL/glut.h libpng-development png /usr/pkg/include/png.h build-utilities gcc /usr/bin/gcc xorg-development modular-xorg-libs /usr/pkg/lib/libX11.so, /usr/X11R7/lib/libX11.so bison bison /usr/pkg/bin/bison flex flex /usr/bin/flex imlib2-development imlib2 /usr/pkg/include/Imlib2.h portaudio-development portaudio /usr/pkg/include/portaudio.h glew glew /usr/pkg/include/GL/glew.h java openjdk /usr/pkg/openjdk/bin/java scons scons /usr/pkg/bin/scons zlib-development zlib /usr/pkg/include/zlib.h jpeg-development jpeg /usr/pkg/include/jpeglib.h perl perl /usr/pkg/bin/perl xorg-video libXv libXvMC /usr/pkg/include/X11/extensions/Xvlib.h, /usr/pkg/include/X11/extensions/XvMClib.h openal-development openal /usr/pkg/include/AL/al.h vorbis-development libvorbis /usr/pkg/include/vorbis/vorbisfile.h jam jam /usr/pkg/bin/jam qt4-development qt4-tools /usr/pkg/qt4/bin/qmake autoconf autoconf /usr/pkg/bin/autoconf libtool libtool-base /usr/pkg/bin/libtool python python /usr/pkg/bin/python yasm yasm /usr/pkg/bin/yasm lib3ds lib3ds /usr/include/lib3ds/atmosphere.h phoronix-test-suite/pts-core/external-test-dependencies/xml/optware-packages.xml0000644000175000017500000000731011623753433030364 0ustar michaelmichael Optware Palm, HP gtk-development gtk /opt/include/gtk-2.0 sdl-development sdl sdl-devel /opt/include/SDL/SDL.h csh tcsh /opt/bin/tcsh libpng-development libpng /opt/include/libpng12/png.h build-utilities gcc make automake /opt/bin/gcc, /opt/bin/make bison bison /opt/bin/bison flex flex /opt/bin/flex scons scons /opt/bin/scons zlib-development zlib /opt/include/zlib.h jpeg-development libjpeg /opt/include/jpeglib.h perl perl /opt/bin/perl vorbis-development libvorbis /opt/include/vorbis/vorbisfile.h jam jamvm /opt/bin/jam autoconf autoconf /opt/bin/autoconf libtool libtool /opt/bin/libtool ncurses-development ncurses /opt/include/ncurses.h popt popt /opt/include/popt.h curl libcurl libcurl-dev /opt/lib/libcurl.so.3 boost-development boot-date-time boost-dev boost-system boost-thread boost-signals boost-regex /opt/include/boost/ bzip2-development bzip2 /opt/include/bzlib.h tcl tcl /opt/bin/tclsh glibc-development libc-dev /opt/lib/libc.a python python /opt/bin/python phoronix-test-suite/pts-core/external-test-dependencies/xml/zenwalk-packages.xml0000644000175000017500000001562311711520517030355 0ustar michaelmichael Zenwalk gtk-development gtk+2 /usr/include/gtk-2.0 sdl-development SDL_Pango SDL_gfx SDL_perl SDL_sound sdl /usr/include/SDL/SDL.h, /usr/include/SDL/SDL_gfxPrimitives.h, /usr/include/SDL/SDL_net.h, /usr/include/SDL/SDL_image.h, /usr/include/SDL/SDL_ttf.h glut plib /usr/lib/libglut.so.3, /usr/include/GL/glut.h csh tcsh /bin/csh libpng-development libpng /usr/include/libpng12/png.h build-utilities gcc gcc-g++ gcc-objc automake pkg-config /usr/bin/gcc xorg-development xorg-utils xorg-libs /usr/lib/libXmu.so, /usr/lib/libXmuu.so, /usr/lib/libXi.a bison bison /usr/bin/bison flex flex /usr/bin/flex imlib2-development imblib2 /usr/lib/imlib2 java jdk /usr/bin/java portaudio-development portaudio /usr/include/portaudio.h fortran-compiler gcc-gfortran /usr/bin/gfortran glew glew /usr/include/GL/glew.h cairo-development cairo /usr/include/cairo/cairo.h freeimage freeimage /usr/lib/libfreeimage.so.3, /usr/include/FreeImage.h scons scons /usr/bin/scons zlib-development zlib /usr/include/zlib.h jpeg-development libjpeg /usr/include/jpeglib.h libaio-development libaio /usr/include/libaio.h perl perl /usr/bin/perlcc, /usr/bin/perl, /etc/perl/CPAN, /usr/lib/perl5/auto/SDL_perl/SDL_perl.so, /usr/lib/libperl.a xorg-video xorg-libs /usr/include/X11/extensions/Xvlib.h, /usr/include/X11/extensions/XvMClib.h libstdcpp5 cxxlibs /usr/lib/libstdc++.so.5 openal-development openal /usr/include/AL/al.h vorbis-development libvorbis /usr/include/vorbis/vorbisfile.h jam boost-jam /usr/bin/jam qt4-development qt4-base qt4-devel /usr/bin/qmake-qt4, /usr/include/qt4/Qt/qgl.h autoconf autoconf /usr/bin/autoconf libtool libtool /usr/bin/libtool ncurses-development ncurses /usr/include/ncurses.h popt popt /usr/include/popt.h curl curl /usr/lib/libcurl.so.3, /usr/bin/curl fftw3-development fftw /usr/include/fftw3.h blas-development lapack /usr/include/cblas.h lapack-development lapack /usr/lib/liblapack.so cmake cmake /usr/bin/cmake boost-development boost /usr/include/boost/ bzip2-development bzip2 /usr/include/bzlib.h tcl tcl /usr/bin/tclsh python python /usr/bin/python yasm yasm /usr/bin/yasm gmp-library gmp /usr/include/gmp.h phoronix-test-suite/pts-core/external-test-dependencies/xml/opensolaris-packages.xml0000644000175000017500000001073511564533734031252 0ustar michaelmichael OpenSolaris gtk-development SUNWgnome-base-libs SUNWGtk /usr/include/gtk-2.0, /usr/lib/libgtk.so sdl-development SUNWlibsdl /usr/include/SDL/SDL.h glut SUNWxorg-mesa /usr/X11/include/GL/gl.h csh SUNWtcsh /usr/bin/tcsh libpng-development SUNWpng /usr/include/png.h build-utilities gcc-432 SUNWgmake gcc-dev-4 /usr/bin/gcc OR /opt/csw/gcc4/bin/gcc, /usr/bin/gmake xorg-development SUNWxorg-headers /usr/X11/include/X11/ xorg-video SUNWxorg-headers /usr/X11/include/X11/extensions/Xvlib.h, /usr/X11/include/X11/extensions/XvMClib.h bison SUNWbison /usr/sfw/bin/bison flex SUNWflexlex /usr/sfw/bin/flex java SUNWj6rt /usr/bin/java zlib-development SUNWzlib /usr/include/zlib.h jpeg-development SUNWjpg /usr/include/jpeglib.h perl SUNWperl584core /usr/bin/perl libstdcpp5 SUNWgccruntime /usr/sfw/lib/libstdc++.so vorbis-development SUNWogg-vorbis /usr/include/vorbis/vorbisfile.h autoconf SUNWaconf /usr/bin/autoconf libtool SUNWlibtool /usr/bin/libtool ncurses-development SUNWncurses /usr/gnu/include/ncurses/curses.h OR /usr/include/ncurses/curses.h popt SUNWlibpopt /usr/include/popt.h curl SUNWcurl /usr/lib/libcurl.so.3 tcl SUNWTcl /usr/bin/tclsh cmake SUNWcmake /usr/bin/cmake bzip2-development SUNWbzip /usr/include/bzlib.h glibc-development SUNWlibC /usr/lib/libC.so.5 python SUNWPython /usr/bin/python phoronix-test-suite/pts-core/external-test-dependencies/xml/openindiana-packages.xml0000644000175000017500000001173011564533734031175 0ustar michaelmichael OpenIndiana gtk-development library/desktop/gtk2 /usr/include/gtk-2.0, /usr/lib/libgtk.so sdl-development library/sdl /usr/include/SDL/SDL.h glut x11/library/mesa /usr/X11/include/GL/gl.h csh SUNWcs /usr/bin/tcsh build-utilities developer/gcc/gcc-43 developer/build/gnu-make /usr/bin/gcc OR /usr/gcc/ OR /opt/csw/gcc4/bin/gcc, /usr/bin/gmake xorg-development FSWxorg-headers x11/server/xorg /usr/X11/include/X11/ xorg-video FSWxorg-headers /usr/X11/include/X11/extensions/Xvlib.h, /usr/X11/include/X11/extensions/XvMClib.h bison developer/parser/bison /usr/sfw/bin/bison flex developer/lexer/flex /usr/sfw/bin/flex java openjdk7-dev developer/openjdk7/tools /usr/bin/java zlib-development library/zlib /usr/include/zlib.h jpeg-development image/library/libjpeg /usr/include/jpeglib.h perl runtime/perl-584 /usr/bin/perl libstdcpp5 system/library/gcc-3-runtime /usr/sfw/lib/libstdc++.so vorbis-development codec/ogg-vorbis /usr/include/vorbis/vorbisfile.h autoconf developer/build/autoconf /usr/bin/autoconf libtool developer/build/libtool /usr/bin/libtool ncurses-development library/ncurses /usr/gnu/include/ncurses/curses.h OR /usr/include/ncurses/curses.h popt library/popt /usr/include/popt.h curl web/curl /usr/lib/libcurl.so.3 tcl runtime/tcl-8 /usr/bin/tclsh cmake developer/build/cmake /usr/bin/cmake bzip2-development compress/bzip2 /usr/include/bzlib.h glibc-development system/library /usr/lib/libC.so.5 python runtime/python-26 /usr/bin/python gmp-library library/gmp /usr/include/gmp.h python-numpy library/python-2/python-extra-26 /usr/share/pyshared/numpy/version.py openmpi-development developer/clustertools-821 /opt/SUNWhpc/ phoronix-test-suite/pts-core/external-test-dependencies/xml/pardus-packages.xml0000644000175000017500000001471211711520434030174 0ustar michaelmichael Pardus Linux gtk-development gtk2 /usr/include/gtk-2.0 sdl-development libsdl sdl-net sdl-image /usr/include/SDL/SDL.h, /usr/include/SDL/SDL_net.h, /usr/include/SDL/SDL_image.h glut glut /usr/lib/libglut.so.3, /usr/include/GL/glut.h csh tcsh /bin/csh libpng-development libpng /usr/include/libpng12/png.h build-utilities gcc /usr/bin/gcc xorg-development xorg-server /usr/include/xorg bison bison /usr/bin/bison flex flex /usr/bin/flex imlib2-development imlib2 /usr/include/Imlib2.h java sun-jre /opt/sun-jdk/jre/bin/java portaudio-development portaudio /usr/include/portaudio.h fortran-compiler gcc /usr/bin/gfortran glew glew /usr/include/GL/glew.h freeimage FreeImage /usr/lib/libfreeimage.so.3 scons scons /usr/bin/scons zlib-development zlib /usr/include/zlib.h jpeg-development jpeg /usr/include/jpeglib.h libaio-development libaio /usr/include/libaio.h cairo-development cairo /usr/include/cairo/cairo.h perl perl /usr/bin/perl xorg-video libXv libXvMC /usr/include/X11/extensions/Xvlib.h, /usr/include/X11/extensions/XvMClib.h libstdcpp5 libstdc++ /usr/lib/libstdc++-v3/libstdc++.so.5 openal-development openal /usr/include/AL/al.h, /usr/lib/libopenal.so.0 vorbis-development taglib /usr/include/taglib/vorbisfile.h jam jam /usr/bin/jam qt4-development qt4 /usr/qt/4/bin/qmake autoconf autoconf /usr/bin/autoconf libtool libtool /usr/bin/libtool ncurses-development ncurses /usr/include/ncurses.h popt popt /usr/include/popt.h curl libcurl curl /usr/lib/libcurl.so.3, /usr/bin/curl fftw3-development fftw3 /usr/include/fftw3.h blas-development blas /usr/include/cblas.h lapack-development lapack /usr/lib/liblapack.so cmake cmake /usr/bin/cmake boost-development boost /usr/include/boost/ tcl tcl /usr/bin/tclsh python python /usr/bin/python yasm yasm /usr/bin/yasm lib3ds lib3ds /usr/include/lib3ds/atmosphere.h phoronix-test-suite/pts-core/external-test-dependencies/xml/pclinuxos-packages.xml0000644000175000017500000001665011711520477030734 0ustar michaelmichael PCLinuxOS gtk-development libgtk+2.0_0-devel /usr/include/gtk-2.0 sdl-development libSDL1.2-devel libSDL_gfx14-devel libSDL_net1.2-devel libSDL_image1.2-devel libSDL_ttf2.0-devel /usr/include/SDL/SDL.h, /usr/include/SDL/SDL_gfxPrimitives.h, /usr/include/SDL/SDL_net.h, /usr/include/SDL/SDL_image.h, /usr/include/SDL/SDL_ttf.h cairo-development libcairo-devel /usr/include/cairo/cairo.h glut libmesaglut3-devel /usr/include/GL/glut.h csh tcsh /bin/csh libpng-development libpng-devel /usr/include/libpng12/png.h build-utilities gcc gcc-cpp /usr/bin/gcc xorg-development libxorg-x11-devel /usr/lib/libXmu.so, /usr/lib/libXmuu.so, /usr/lib/libXi.a bison bison /usr/bin/bison flex flex /usr/bin/flex imlib2-development libimlib2_1 /usr/lib/imlib2 java java-1.6.0-sun /usr/bin/java portaudio-development libportaudio2-devel /usr/include/portaudio.h fortran-compiler gcc-gfortran /usr/bin/gfortran glew libglew1.3-devel /usr/include/GL/glew.h freeimage libFreeImage3-devel /usr/include/FreeImage.h scons scons /usr/bin/scons zlib-development zlib1-devel /usr/include/zlib.h jpeg-development libjpeg62-staticdevel /usr/include/jpeglib.h libaio-development libaio1-devel /usr/include/libaio.h perl perl /usr/bin/perl xorg-video libxv1-devel libxvmc1-devel /usr/include/X11/extensions/Xvlib.h, /usr/include/X11/extensions/XvMClib.h libstdcpp5 libstdc++5 /usr/lib/libstdc++.so.5 openal-development libopenal0-devel /usr/include/AL/al.h vorbis-development libvorbis0-devel /usr/include/vorbis/vorbisfile.h jam jam /usr/bin/jam qt4-development libqt4-devel /usr/bin/qmake-qt4 autoconf autoconf /usr/bin/autoconf libtool libtool /usr/bin/libtool ncurses-development libncurses5-devel /usr/include/ncurses.h popt popt-devel /usr/include/popt.h curl libcurl3 curl /usr/lib/libcurl.so.3, /usr/bin/curl fftw3-development libfftw3-devel /usr/include/fftw3.h blas-development blas-devel /usr/include/cblas.h lapack-development lapack /usr/lib/liblapack.so cmake cmake /usr/bin/cmake boost-development libboost-devel /usr/include/boost/ bzip2-development libbzip2-devel /usr/include/bzlib.h tcl tcl /usr/bin/tclsh python python /usr/bin/python atlas-development atlas /usr/lib/libatlas.a openmpi-development openmpi /usr/lib/openmpi/lib/libmpi.so, /usr/bin/mpirun.openmpi yasm yasm /usr/bin/yasm lib3ds lib3ds-devel /usr/include/lib3ds/atmosphere.h gmp-library libgmp3 /usr/include/gmp.h phoronix-test-suite/pts-core/external-test-dependencies/xml/macports-packages.xml0000664000175000017500000001137612106536221030533 0ustar michaelmichael MacPorts Mac OS X port common-dependencies glxinfo glxinfo gtk-development gtk2 sdl-development libsdl-devel libsdl_gfx libsdl_image libsdl_mixer libsdl_sound libsdl_ttf glut freeglut csh tcsh libpng-development libpng openssl-development openssl build-utilities gcc48 automake autoconf gmake cairo-development cairo cairo-devel bison bison flex flex imlib2-development libimlib2 java openjdk6 portaudio-development portaudio fortran-compiler gcc48 glew glew lib3ds lib3ds freeimage freeimage scons scons zlib-development zlib jpeg-development jpeg libstdcpp5 libstdcxx libstdcxx-devel openal-development openal vorbis-development libvorbis jam jam p7zip p7zip qt4-development qt4-mac autoconf autoconf libtool libtool ncurses-development ncurses popt popt curl curl fftw3-development fftw fftw-3 openmpi-development mpich mpich-devel mpich2 openmpi cmake cmake boost-development boost bzip2-development bzip2 tcl tcl yasm yasm gmp-library gmp subversion subversion git git-core phoronix-test-suite/pts-core/external-test-dependencies/xml/mandrivalinux-packages.xml0000644000175000017500000001416312161407113031555 0ustar michaelmichael Mandriva Mageia, OpenMandriva urpmi gtk-development gtk+2-devel sdl-development libSDL1.2_0 libSDL_gfx13 libSDL_image1.2_0 libSDL_net1.2_0 libSDL_ttf2.0_0 cairo-development cairo-devel openssl-development openssl p7zip p7zip csh tcsh libpng-development png-devel build-utilities task-c-devel task-c++-devel /usr/bin/gcc, /usr/bin/bison, /usr/bin/flex xorg-development libxorg-x11-devel bison bison flex flex imlib2-development imlib2-devel java java portaudio-development portaudio-devel fortran-compiler gcc-gfortran glew glew-devel freeimage freeimage-devel scons scons zlib-development zlib1-devel jpeg-development libopenjpeg-devel libaio-development libaio-devel perl perl perl-SDL perl-opengl libopengl-perl /usr/lib/perl5/auto/OpenGL/OpenGL.so xorg-video libxv1-devel libxvmc1-devel libstdcpp5 libstdc++5 openal-development openal-devel vorbis-development libvorbis-devel jam ftjam /usr/bin/bjam qt4-development libqt4-devel /usr/lib/qt4/bin/qmake autoconf autoconf libtool libtool ncurses-development libncurses5-devel popt popt curl libcurl4 curl fftw3-development libfftw-devel blas-development libblas-devel lapack-development liblapack-devel cmake cmake boost-development libboost-devel bzip2-development libbzip2-devel tcl tcl glibc-development glibc-devel python python atlas-development libatlas-devel openmpi-development libopenmpi yasm yasm lib3ds lib3ds-devel gmp-library libgmp-devel subversion subversion git git superlu superlu phoronix-test-suite/pts-core/external-test-dependencies/xml/gentoo-packages.xml0000644000175000017500000001446512212733023030173 0ustar michaelmichael Gentoo emerge gtk-development x11-libs/gtk+ sdl-development media-libs/libsdl media-libs/sdl-net media-libs/sdl-image glut virtual/glut openssl-development dev-libs/openssl cairo-development x11-libs/cairo csh app-shells/tcsh p7zip app-arch/p7zip libpng-development media-libs/libpng build-utilities sys-devel/gcc xorg-development x11-base/xorg-server bison sys-devel/bison flex sys-devel/flex imlib2-development media-libs/imlib2 java virtual/jre portaudio-development media-libs/portaudio fortran-compiler sys-devel/gcc glew media-libs/glew freeimage media-libs/freeimage scons dev-util/scons zlib-development sys-libs/zlib jpeg-development media-libs/jpeg libaio-development dev-libs/libaio perl dev-lang/perl xorg-video x11-libs/libXvMC x11-libs/libXv libstdcpp5 virtual/libstdc++-3.3 openal-development media-libs/openal vorbis-development media-libs/taglib jam dev-util/ftjam qt4-development x11-libs/qt-core autoconf sys-devel/autoconf libtool sys-devel/libtool ncurses-development sys-libs/ncurses popt dev-libs/popt numa-development sys-process/numactl curl net-misc/curl fftw3-development sci-libs/fftw blas-development virtual/blas lapack-development virtual/lapack cmake dev-util/cmake boost-development dev-libs/boost bzip2-development dev-haskell/bzlib tcl dev-lang/tcl glibc-development dev-libs/libpthread-stubs python dev-lang/python /usr/bin/python atlas-development sci-libs/lapack-atlas openmpi-development sys-cluster/openmpi libmpi.so, mpirun yasm dev-lang/yasm lib3ds media-libs/lib3ds gmp-library dev-libs/gmp subversion dev-vcs/subversion git dev-vcs/git superlu sci-libs/superlu libtool sys-devel/libtool phoronix-test-suite/pts-core/external-test-dependencies/xml/freebsd-packages.xml0000644000175000017500000001331012176026254030310 0ustar michaelmichael FreeBSD gtk-development x11-toolkits/gtk20 sdl-development devel/sdl12 graphics/sdl_gfx graphics/sdl_image graphics/sdl_ttf audio/sdl_sound audio/sdl_mixer graphics/linux-f10-sdl_image graphics/linux-sdl_ttf devel/linux-f10-sdl12 glut graphics/freeglut csh shells/44bsd-csh 44bsd-csh libpng-development graphics/png openssl-development security/openssl build-utilities devel/autoconf cairo-development graphics/cairo bison devel/bison flex textproc/flex imlib2-development graphics/imlib2 java java/openjdk7 portaudio-development audio/portaudio fortran-compiler lang/g95 g95 glew graphics/glew lib3ds graphics/lib3ds freeimage graphics/freeimage scons devel/scons jpeg-development graphics/libjpeg-turbo libaio-development emulators/linux-libaio perl lang/perl5.14 openal-development audio/openal vorbis-development audio/libvorbis audio/linux-f10-libvorbis audio/linux-f10-alsa-lib jam devel/jam p7zip archivers/p7zip qt4-development x11-toolkits/qt4-gui autoconf devel/autoconf libtool devel/libtool ncurses-development devel/ncurses popt devel/popt curl ftp/curl fftw3-development math/fftw blas-development math/blas lapack-development math/lapack atlas-development devel/atlas /usr/local/include/Atlas-C++-0.5 openmpi-development net/openmpi net/mpich2 cmake devel/cmake boost-development devel/boost-all bzip2-development archivers/bzip2 tcl devel/tcllib python lang/python python-boost-development devel/boost-python-libs yasm devel/yasm gmp-library math/gmp subversion devel/subversion git devel/git superlu math/superlu phoronix-test-suite/pts-core/external-test-dependencies/xml/ubuntu-packages.xml0000644000175000017500000002043412222371126030216 0ustar michaelmichael Ubuntu Debian, Linux Mint, MEPIS, Nexenta Core, PTS Linux Live, PTS Desktop Live, Joli Cloud, gNewSense, Fluxbuntu, Mythbuntu, Goobuntu, GNU KFreeBSD, Linaro apt-get common-dependencies mesa-utils unzip glxinfo, unzip 32bit-compatibility libc6-i386 libc6:i386 libstdc++6:i386 libx11-6:i386 libxext6:i386 libxrandr2:i386 libxinerama1:i386 libxdamage-dev:i386 libgl1-mesa-dev:i386 libglu1-mesa-dev x86_64 /usr/share/doc/ia32-libs 32bit-compatibility ia32-libs x86_64 8.04, 8.10, 9.04, 9.10, 10.04, 10.10, 11.04, 11.10, 12.04, 12.10, 13.04 /usr/share/doc/ia32-libs gtk-development libgtk2.0-dev sdl-development libsdl1.2-dev libsdl-gfx1.2-dev libsdl-net1.2-dev libsdl-image1.2-dev libsdl-ttf2.0-dev libsdl-mixer1.2-dev glut freeglut3-dev csh csh libpng-development libpng12-dev openssl-development libssl-dev build-utilities build-essential autoconf /usr/share/build-essential cairo-development libcairo2-dev libgdk-pixbuf2.0-dev cairo/cairo.h, gdk-pixbuf-2.0/gdk-pixbuf/gdk-pixbuf.h xorg-development xorg-dev bison bison flex flex imlib2-development libimlib2-dev java openjdk-6-jre portaudio-development libportaudio-dev fortran-compiler gfortran glew libglew1.5-dev lib3ds lib3ds-dev freeimage libfreeimage3 libfreeimage-dev scons scons zlib-development zlib1g-dev jpeg-development libjpeg-dev jpeglib.h libaio-development libaio-dev perl perl perl-base perl-modules libsdl-perl libperl-dev libpcre3-dev perl, /etc/perl/CPAN, perl5/auto/SDL_perl/SDL_perl.so, pcre.h perl-opengl libopengl-perl perl5/auto/OpenGL/OpenGL.so xorg-video libxv-dev libxvmc-dev libstdcpp5 libstdc++5 openal-development libopenal-dev vorbis-development libvorbis-dev jam jam p7zip p7zip-full qt4-development libqt4-dev libqt4-opengl-dev qmake-qt4, qt4/Qt/qgl.h autoconf autoconf libtool libtool ncurses-development libncurses5-dev popt libpopt-dev numa-development libnuma-dev curl libcurl3 curl fftw3-development libfftw3-dev fftw-dev blas-development libblas-dev lapack-development liblapack-dev atlas-development libatlas-base-dev openmpi-development libopenmpi-dev openmpi-bin libmpich2-dev libmpich1.0-dev cmake cmake boost-development libboost-all-dev libasio-dev libboost-iostreams-dev boost/regex.hpp, boost/iostreams/write.hpp bzip2-development libbz2-dev tcl tcl glibc-development libc6-dev glibc-development libc6-dev-i386 /usr/lib32/libc.so x86_64 python python python-boost-development libboost-python-dev boost-thread-development libboost-thread-dev python-numpy python-numpy /usr/share/pyshared/numpy/version.py yasm yasm gmp-library libgmp3-dev subversion subversion git git-core superlu libsuperlu3-dev phoronix-test-suite/pts-core/external-test-dependencies/xml/fedora-packages.xml0000644000175000017500000001502712222574305030142 0ustar michaelmichael Fedora Moblin, MeeGo, Amazon, Red Hat Enterprise, Red Hat Enterprise Server, Scientific, ScientificSL, CentOS, ClearOS, ClearOS Core Server, Oracle Server, OLPC yum 32bit-compatibility glibc.i686 libstdc++.i686 libX11.i686 libXext.i686 libXrandr.i686 libXinerama.i686 mesa-libGL.i686 openal-soft.i686 x86_64 /lib/i686, /usr/lib/libstdc++.so.6 gtk-development gtk2-devel sdl-development SDL-devel SDL_gfx-devel SDL_image-devel SDL_net-devel SDL_sound-devel SDL_ttf-devel glut freeglut-devel openssl-development openssl-devel csh tcsh cairo-development cairo-devel libpng-development libpng-devel build-utilities gcc gcc-c++ make autoconf automake glibc-static patch xorg-development xorg-x11-server-devel bison bison flex flex imlib2-development imlib2-devel java java-openjdk portaudio-development portaudio-devel fortran-compiler gcc-gfortran glew glew-devel freeimage freeimage freeimage-devel scons scons zlib-development zlib-devel jpeg-development libjpeg-devel libaio-development libaio-devel perl perl perl-SDL pcre-devel xorg-video libXv-devel libXvMC-devel libstdcpp5 compat-libstdc++-33 p7zip p7zip openal-development openal openal-devel vorbis-development taglib-devel libvorbis-devel jam jam qt4-development qt4-devel autoconf autoconf libtool libtool ncurses-development ncurses-devel popt popt-devel numa-development numactl-devel curl libcurl curl fftw3-development fftw3-devel blas-development blas blas-devel lapack-development lapack-devel cmake cmake boost-development boost-devel bzip2-development bzip2-devel tcl tcl glibc-development glibc-devel python python atlas-development atlas-devel openmpi-development openmpi-devel openmpi mpich2-devel openmpi/lib/libmpi.so yasm yasm lib3ds lib3ds-devel gmp-library gmp-devel subversion subversion git git superlu superlu phoronix-test-suite/pts-core/external-test-dependencies/xml/generic-packages.xml0000644000175000017500000003037312216205245030314 0ustar michaelmichael common-dependencies Common Dependencies For The Phoronix Test Suite 32bit-compatibility 32-bit Libraries / Compatibility For Linux x86_64 ia32-libs /usr/lib32/ gtk-development GTK Development Files libgtk2.0-dev gtk-2.0/gtk/gtk.h sdl-development SDL Development Files libsdl1.2-dev, sdl-net, sdl-image SDL/SDL.h, SDL/SDL_net.h, SDL/SDL_image.h glut OpenGL Utility Kit / GLUT freeglut3-dev, freeglut-devel libglut.so.3, GL/glut.h csh CSH csh, tcsh csh OR bsd-csh libpng-development PNG Library Development Files libpng12-dev libpng12/png.h openssl-development OpenSSL Development Files libssl-dev, openssl-devel openssl/ssl.h build-utilities Compiler / Development Libraries gcc gcc OR clang OR cc xorg-development X.Org Development Files and Libraries xserver-xorg-development, xorg-devel xorg/xf86.h cairo-development Cairo Development Files and Libraries cairo-devel, libcairo2-dev, libcairo-devel cairo/cairo.h bison Bison bison bison flex Flex flex flex p7zip 7-Zip / p7zip p7zip, p7zip-full 7za imlib2-development Imlib2 Development Files libimlib2-dev Imlib2.h, libImlib2.so java Java Runtime Environment java-openjdk, icedtea, java, sun-java java OR jvm OR /usr/lib64/jvm portaudio-development PortAudio Development Files libportaudio-dev, portaudio-devel portaudio.h ncurses-development NCurses Development Files libncurses5-dev ncurses.h fortran-compiler Fortran Compiler gfortran, gcc-fortran gfortran glew OpenGL Extension Wrangler libglew, libglew1.5-dev, glew-devel GL/glew.h freeimage FreeImage Graphics Library libfreeimage3, libfreeimage-dev, libfreeimage.so.3, FreeImage.h scons SCons scons scons zlib-development Zlib Compression Library zlib1-devel, zlib-devel, zlib1g-dev zlib.h jpeg-development Development Files For IJG JPEG Library libjpeg62-devel, libjpeg62-dev, libjpeg-devel jpeglib.h libaio-development Linux Kernel AIO Development Files libaio-dev, libaio-devel libaio.h perl Support For PERL Language perl, perl-base perl perl-opengl OpenGL Support For PERL Language perl-opengl, perl-OpenGL-Simple perl5/auto/OpenGL/OpenGL.so xorg-video Xv and XvMC Library Files xorg-x11-libXv-devel, xorg-x11-devel, libxv-dev, libxvmc-dev X11/extensions/Xvlib.h, X11/extensions/XvMClib.h libstdcpp5 GNU Standard C++ Library v3 compat-libstdc++-33, libstdc++5 libstdc++.so.5 openal-development OpenAL Library And Development Files openal, openal-devel, libopenal0a, libopenal-dev AL/al.h vorbis-development Vorbis Audio Development Files libvorbis-dev, vorbis-devel vorbis/vorbisfile.h jam Jam Build Tool jam jam OR jam.perforce qt4-development Qt4 Development Files libqt4-dev, libqt4-devel, qt4-devel qmake OR qmake-qt4 autoconf Autoconf autoconf autoconf libtool Libtool libtool libtool popt Popt popt, popt-devel, libpopt-dev popt.h numa-development NUMA Development Files libnuma-dev, numactl-devel numa.h curl Curl curl, libcurl3, libcurl libcurl.so.3 OR libcurl.so.4, curl fftw3-development Fast Fourier Transform 3 Library fftw3, libfftw3-dev, libfftw3-devel, fftw3-devel fftw3.h blas-development Basic Linear Algebra Sub-Routine Library libblas-dev, libblas-devel, blas-devel, blas cblas.h lapack-development Linear Algebra Pack liblapack-dev, lapack, lapack-devel, liblapack-devel liblapack.so atlas-development Linear Algebra Pack libatlas-base-dev libatlas.a openmpi-development OpenMPI libopenmpi-dev, openmpi-bin openmpi/lib/libmpi.so, mpirun.openmpi cmake CMake cmake cmake boost-development Boost Development Libraries boost-devel, libboost-dev, libboost-devel boost/regex.hpp bzip2-development BZIP2 Development Libraries bzip2-devel, libbz2-dev, libbzip2-devel bzlib.h tcl Tool Command Language tcl tclsh glibc-development GNU C Development Libraries w/ 32-bit Support libc6-dev, libc6-dev-i386, glibc-devel gnu/stubs-32.h OR gnu-versions.h, libc.a python Python python python python-boost-development Python Boost Development Libraries libboost-python-dev boost/python.hpp boost-thread-development Boost Thread Development Libraries libboost-thread-dev boost/thread.hpp python-numpy Python Numpy python-numpy /usr/shared/pyshared/numpy/version.py yasm Yasm Assembler yasm yasm lib3ds AutoDesk 3DS File Support lib3ds libs3ds-devel lib3ds/atmosphere.h gmp-library The GNU Multiple Precision Arithmetic Library libgmp3-dev, libgmp3, gmp-devel gmp.h opencl OpenCL NVIDIA OpenCL, ATI Stream SDK, OpenCL SDK CL/cl.h OR OpenCL/cl.h OR /usr/local/cuda OR /usr/cuda subversion Subversion Subversion svn git Git git, git-core git superlu SuperLU superlu, libsuperlu3-dev superlu/slu_util.h phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-opensuse-packages.sh0000755000175000017500000000034012120152013032664 0ustar michaelmichael#!/bin/sh # OpenSuSE package installation echo "Please enter your root password below:" 1>&2 if [ -x /usr/bin/zypper ]; then su root -c "zypper install -l -y --force-resolution $*" else su root -c "yast -i $*" fi exit phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-freebsd-packages.sh0000755000175000017500000000134612102064723032456 0ustar michaelmichael#!/bin/sh # FreeBSD package installation echo "For now with this test profile script, please run: phoronix-test-suite install-dependencies xxx as root." # sudo seems a bit odd at times on PC-BSD 9.1 # Check that ports is setup, below code should work for making sure good state with PC-BSD at least if [ -d /usr/ports/distfiles ] && [ ! -d /usr/ports/devel ] && [ -x /usr/sbin/portsnap ]; then portsnap fetch extract fi for portdir in $* do if [ -d /usr/ports/$portdir ]; then cd /usr/ports/$portdir make config-recursive install clean BATCH="yes" fi done #echo "Please enter your root password below:" 1>&2 #su root -c "PACKAGESITE=\"ftp://ftp.freebsd.org/pub/FreeBSD/ports/i386/packages-7-stable/Latest/\" pkg_add -r $*" #exit phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-dragonfly-packages.sh0000775000175000017500000000106312102103106033014 0ustar michaelmichael#!/bin/sh # DragonFlyBSD pkgsrc package installation echo "For now with this test profile script, please run: phoronix-test-suite install-dependencies xxx as root." # Check that pkgsrc is setup, below code should work for making sure good state with at least DragonFlyBSD if [ -d /usr/pkgsrc ] && [ ! -d /usr/pkgsrc/devel ]; then cd /usr if [ -d /usr/pkgsrc/.git ]; then make pkgsrc-update else make pkgsrc-create fi fi for portdir in $* do if [ -d /usr/pkgsrc/$portdir ]; then cd /usr/pkgsrc/$portdir bmake install clean BATCH="yes" fi done phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-zenwalk-packages.sh0000755000175000017500000000020311564533734032524 0ustar michaelmichael#!/bin/sh # Zenwalk package installation echo "Please enter your root password below:" 1>&2 su root -c "echo 1 | netpkg $*" exit phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-macports-packages.sh0000664000175000017500000000003712106536357032702 0ustar michaelmichael#!/bin/sh sudo port install $* phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-pclinuxos-packages.sh0000755000175000017500000000120511564533734033100 0ustar michaelmichael#!/bin/sh # Portions based on Debian fglrx install script # http://phorogit.com/index.php?p=fglrx-packaging.git&b=c67ac96d765ca95130bd07cb240ab69cfc06baa2 if [ `whoami` != "root" ]; then if [ -x /usr/bin/gksudo ] && [ ! -z "$DISPLAY" ]; then ROOT="/usr/bin/gksudo" elif [ -x /usr/bin/kdesu ] && [ ! -z "$DISPLAY" ]; then ROOT="/usr/bin/kdesu" elif [ -x /usr/bin/sudo ]; then ROOT="/usr/bin/sudo" fi else ROOT="" fi # if [ -x /usr/sbin/synaptic ] && [ ! -z "$DISPLAY" ]; then # $ROOT "sh -c 'echo \"$@ install\" | /usr/sbin/synaptic --set-selections --non-interactive --hide-main-window'" # else $ROOT "apt-get -y install $*" # fi phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-pardus-packages.sh0000755000175000017500000000023111564533734032350 0ustar michaelmichael#!/bin/sh # Pardus package installation echo "Please enter your root password below:" 1>&2 su root -c "pisi install --ignore-safety --yes-all $*" exit phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-optware-packages.sh0000755000175000017500000000016611564533734032542 0ustar michaelmichael#!/bin/sh # http://ipkg.nslu2-linux.org/feeds/optware/cs08q1armel/cross/unstable/ /opt/bin/sudo ipkg-opt install $* phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-opensolaris-packages.sh0000755000175000017500000000020011564533734033404 0ustar michaelmichael#!/bin/sh # OpenSolaris IPS Installer echo "Please enter your root password below:" 1>&2 su root -c "pkg install --accept $*" phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-openindiana-packages.sh0000755000175000017500000000020011564533734033333 0ustar michaelmichael#!/bin/sh # OpenSolaris IPS Installer echo "Please enter your root password below:" 1>&2 su root -c "pkg install --accept $*" phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-netbsd-packages.sh0000755000175000017500000000017211564533734032335 0ustar michaelmichael#!/bin/sh # NetBSD package installation echo "Please enter your root password below:" 1>&2 su root -c "pkg_add $*" exit phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-mandrivalinux-packages.sh0000755000175000017500000000020311564533734033732 0ustar michaelmichael#!/bin/sh # Mandriva package installation echo "Please enter your root password below:" 1>&2 su - root -c "urpmi --auto $*" exit phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-gentoo-packages.sh0000755000175000017500000000017611564533734032355 0ustar michaelmichael#!/bin/sh # Gentoo package installation echo "Please enter your root password below:" 1>&2 su root -c "emerge -v $*" exit phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-fedora-packages.sh0000755000175000017500000000021711564533734032316 0ustar michaelmichael#!/bin/sh # Fedora package installation echo "Please enter your root password below:" 1>&2 su root -c "yum -y --skip-broken install $*" exit phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-debian-packages.sh0000755000175000017500000000051111564533734032275 0ustar michaelmichael#!/bin/sh # Debian, unlike Ubuntu, doesn't sudo it users by default if [ -x /usr/bin/aptitude ]; then # aptitude is nice since it doesn't fail if a non-existant package is hit # See: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=503215 su -c "aptitude -y install $*" else su -c "apt-get -y --ignore-missing install $*" fi phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-arch-packages.sh0000755000175000017500000000017311564533734031774 0ustar michaelmichael#!/bin/sh # Arch package installation echo "Please enter your root password below:" 1>&2 su root -c "pacman -Sy $*" exit phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-angstrom-packages.sh0000755000175000017500000000003211564533734032703 0ustar michaelmichael#!/bin/sh opkg install $* phoronix-test-suite/pts-core/external-test-dependencies/scripts/install-ubuntu-packages.sh0000755000175000017500000000122212130672161032361 0ustar michaelmichael#!/bin/sh if [ `whoami` != "root" ] && [ ! -z "$DISPLAY" ]; then if [ -x /usr/bin/gksudo ]; then ROOT="/usr/bin/gksudo" elif [ -x /usr/bin/kdesudo ]; then ROOT="/usr/bin/kdesudo" elif [ -x /usr/bin/sudo ]; then ROOT="/usr/bin/sudo" fi elif [ -z "$DISPLAY" ]; then sudo -- apt-get -y --ignore-missing install $* else su -c "apt-get -y --ignore-missing install $*" exit fi if [ -x /usr/bin/aptitude ]; then # aptitude is nice since it doesn't fail if a non-existant package is hit # See: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=503215 $ROOT -- "aptitude -y install $*" else $ROOT -- su -c "apt-get -y --ignore-missing install $*" fi phoronix-test-suite/pts-core/static/certificates/phoromatic-com.pem0000644000175000017500000001212011564533734025741 0ustar michaelmichael-----BEGIN CERTIFICATE----- MIIFXTCCBEWgAwIBAgIHSz9lGWUntjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5 IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky ODcwHhcNMTAxMTIxMDIxMjU4WhcNMTUxMTIxMDIxMjU4WjBVMRcwFQYDVQQKEw5w aG9yb21hdGljLmNvbTEhMB8GA1UECxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVk MRcwFQYDVQQDEw5waG9yb21hdGljLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAK2Tl+mcuc7T033UoINEo6zFQrpSAJSrVKW7swYC6uq3oXY0bnkq SPU6JBbXH3cLQsCB3F9v7G5YvWxAtNirU8G7cRfcJkNQ+QRgBsgana+q3D3XeMoD 7loicugY5ncDXOewfNdWDIJ1sFsnt4VdzFzMytNgNyDNOiEwNp4iwyZd2ubvRx/d bSHIedjrCleShGvFcSsP9j7mdKPvKzzA276XV3939zHhDEYRPqO/agqyW6CY93n8 CBHJ16lYAy8c9MyOW0AHK90SwTw2YcnU0Br8j+/snPb1bN5dCLHyiDB356uUhM// 4+ANXOLv0YlhW/X8NaNboSOOMurhNCmNwq0CAwEAAaOCAbowggG2MA8GA1UdEwEB /wQFMAMBAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB /wQEAwIFoDAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3JsLmdvZGFkZHkuY29t L2dkczEtMjYuY3JsME0GA1UdIARGMEQwQgYLYIZIAYb9bQEHFwEwMzAxBggrBgEF BQcCARYlaHR0cHM6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzCBgAYI KwYBBQUHAQEEdDByMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5nb2RhZGR5LmNv bS8wSgYIKwYBBQUHMAKGPmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20v cmVwb3NpdG9yeS9nZF9pbnRlcm1lZGlhdGUuY3J0MB8GA1UdIwQYMBaAFP2sYTKT bEXW4u6FX5q653aZaMznMC0GA1UdEQQmMCSCDnBob3JvbWF0aWMuY29tghJ3d3cu cGhvcm9tYXRpYy5jb20wHQYDVR0OBBYEFIzsLt1LoOJW+mY55r0DXVEGwwDuMA0G CSqGSIb3DQEBBQUAA4IBAQB8/ZAvevXy2X43kFHOgy41GMh5mlu2SLXfclu6/mnv Xi/Bk4dOb6wEdKX1I+UOLntBq/8I8u1ZCGKkVFTM4RQJayWOmPX+wtOZsvhhGGfi /lTe1TAbeXgEyuHFsEhFLBOGtluxRpbYobCOV/Ka5Q9/aTWa2jqmEDrwKRiyacr3 aMvAucqNMYbpO6UTpMceQeLFYuRwHk5PaXYLxTrz4rATYKEIDvADsvG5JMAQp3YF BVVcfhRWUseDlyilnaSLKpbndX1mjHHxYAlqPqihWSUhdZ4viGyHxHHKjCkqKvd8 0AhWggo7mNQ89gN40khLRoQ5dY91CAWs2v3qntQKf1S/ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ 6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o 0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV U+4= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h /t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf ReYNnyicsbkqWletNw+vHX/bvZ8= -----END CERTIFICATE----- phoronix-test-suite/pts-core/static/certificates/openbenchmarking-server.pem0000644000175000017500000001216211564533734027644 0ustar michaelmichael-----BEGIN CERTIFICATE----- MIIFdTCCBF2gAwIBAgIHK235AyraYDANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5 IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky ODcwHhcNMTAxMTE0MDIyNjEyWhcNMTUxMTE0MDIxMTA0WjBhMR0wGwYDVQQKExRv cGVuYmVuY2htYXJraW5nLm9yZzEhMB8GA1UECxMYRG9tYWluIENvbnRyb2wgVmFs aWRhdGVkMR0wGwYDVQQDExRvcGVuYmVuY2htYXJraW5nLm9yZzCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAKtCjjhKxHYABpFUfHKZWZHd+yedUBCJjYws SEXJgnjk+FWkoqCqbocoySo1qOPlGQPjJEh0Hw3F6JdXNLjxJO8xxT/lfELexdry HrXdaFv7TUYfQSjPhZf74qXvZeUmrHBpWeQL8yXmf0DXfp/zLsLyl8p6px0IPfvJ HVIjoilxVRTwBIdEOuuy4U0ro/Y+lQU6mx1/FUj3yWbnqKV2bCy+2v73lZXmSM/R yPvtCK9kykxQoEAepaDPBSV6lnIUtZvtuW0jmDZKkFSJTSc0iMsuUnmSmg4R3Zmo dOKS+esalQU20k7SOU633lgG1wZsUws4okdqK/l/51D9iOxTpdsCAwEAAaOCAcYw ggHCMA8GA1UdEwEB/wQFMAMBAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF BwMCMA4GA1UdDwEB/wQEAwIFoDAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3Js LmdvZGFkZHkuY29tL2dkczEtMjYuY3JsME0GA1UdIARGMEQwQgYLYIZIAYb9bQEH FwEwMzAxBggrBgEFBQcCARYlaHR0cHM6Ly9jZXJ0cy5nb2RhZGR5LmNvbS9yZXBv c2l0b3J5LzCBgAYIKwYBBQUHAQEEdDByMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz cC5nb2RhZGR5LmNvbS8wSgYIKwYBBQUHMAKGPmh0dHA6Ly9jZXJ0aWZpY2F0ZXMu Z29kYWRkeS5jb20vcmVwb3NpdG9yeS9nZF9pbnRlcm1lZGlhdGUuY3J0MB8GA1Ud IwQYMBaAFP2sYTKTbEXW4u6FX5q653aZaMznMDkGA1UdEQQyMDCCFG9wZW5iZW5j aG1hcmtpbmcub3Jnghh3d3cub3BlbmJlbmNobWFya2luZy5vcmcwHQYDVR0OBBYE FKrgd84yauYdEL0SUGIGiC/D6v1sMA0GCSqGSIb3DQEBBQUAA4IBAQC6Fwoa7LAT QHLeWbJw+wXzv+FYv/qzr5Y1KvPG3lnHH9iqsT1SZlAs6EG5KMch9/BX/eWXEQ2/ yOKJaYqep37vkTkO+LClAQgBHYOStnrw7rOvpZ1ASDhR/Z3qlbsX6BTRVHD+iJZj flpUI6C3qHtYiOSHdJP6cDQD+G9qjGt/Gc2uS8dzPXjzDTji+IVouCrV642t/6PX gljNrk0tYjilEdstYQ9w5Pahw0wyIpzlP8inKEIHrozXgHyahkq3PQEMMoe60S/a a8mhMoOUdYM/gF/fyszbAO4wDk5ViYdTiTkxHjsOhFJMYcXUHs22dSsvYlMevGte a9qov9+3Lh/g -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ 6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o 0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV U+4= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h /t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf ReYNnyicsbkqWletNw+vHX/bvZ8= -----END CERTIFICATE----- phoronix-test-suite/pts-core/static/xsl/pts-test-profile-viewer.xsl0000644000175000017500000001012111564533734025725 0ustar michaelmichael Phoronix Test Suite - <xsl:value-of select="PhoronixTestSuite/TestInformation/Title" />
Test Version
Testing Type
Software Type
Test Options

License
Status
Maintainer
Profile Version
Scale
Proportion
Test Description
Copyright © 2008 - 2010 by Phoronix Media.
phoronix-test-suite/pts-core/static/xsl/pts-test-installation-viewer.xsl0000644000175000017500000000326411310300547026757 0ustar michaelmichael Phoronix Test Suite - Test Installation: <xsl:value-of select="PhoronixTestSuite/TestInstallation/Environment/Name" />

Installed Version:

Install Time:

Installation Time: (seconds)

Last Time Run:

Total Times Run:

Average Run Time: (seconds)

Most Recent Run Time: (seconds)

The Phoronix Test Suite is a product of Phoronix Media.
phoronix-test-suite/pts-core/static/xsl/pts-user-config-viewer.xsl0000644000175000017500000004653112172336630025537 0ustar michaelmichael Phoronix Test Suite - User Configuration File

The user-config.xml file contains the user configuration options for the Phoronix Test Suite. To edit any option, open user-config.xml within your preferred text editor. Alternatively, you can use the user-config-set option with the Phoronix Test Suite to update settings. For example, to set the download cache with the Phoronix Test Suite, execute phoronix-test-suite user-config-set CacheDirectory=~/cache-directory/. For additional information, view the documentation included with the Phoronix Test Suite or visit Phoronix-Test-Suite.com.

OpenBenchmarking Options

AnonymousUsageReporting:

If this option is set to TRUE, anonymous usage information and statistics, like the tests that are run and their length of run, will be reported to OpenBenchmarking.org for analytical reasons. All submitted information is kept anonymous. For more information on the anonymous usage reporting, read the Phoronix Test Suite documentation.

IndexCacheTTL:

The time to live for OpenBenchmarking.org index caches. This is an integer representing the number of days before an index cache should be automatically refreshed from OpenBenchmarking.org. The default value is 3 while setting the value to 0 will disable automatic refreshing of caches (caches can be manually updated at anytime using the respective command).

AlwaysUploadSystemLogs:

If this option is set to TRUE, the system logs (i.e. dmesg, lspci, lsusb, Xorg.0.log) will always be uploaded to OpenBenchmarking.org when uploading your test results. Otherwise the user is prompted whether to attach the system logs with their results.

General Options

DefaultBrowser:

The Phoronix Test Suite will automatically attempt to launch the system's default web browser when needed. This is done first by checking for x-www-browser and then xdg-open. If neither command is available, the Phoronix Test Suite will fallback to checking for Firefox, Epiphany, Mozilla, or the open command. If you wish to override the default browser that the Phoronix Test Suite selects, set this tag to the command name of the browser you wish to use. Leaving this tag empty will have the Phoronix Test Suite determine the default web browser.

UsePhodeviCache:

If this option is set to TRUE, the Phoronix Test Suite will use the Phodevi smart cache (if available). The Phodevi smart cache will automatically cache relevant system hardware/software attributes that can be safely stored and will be used until the system's software/hardware has changed or the system rebooted. Enabling this option will speed up the detection of installed hardware and software through the Phoronix Test Suite. If this option is set to FALSE, Phodevi will not generate a smart cache. The default value is TRUE.

DefaultDisplayMode:

This option affects how text is displayed on the command-line interface during the testing process. If this option is set to DEFAULT, the text interface will be the traditional Phoronix Test Suite output. If this option is set to CONCISE, the display mode is shorter and more concise. This is the default mode used during batch testing. The default value is DEFAULT.

Modules Options

LoadModules:

This tag contains a string of the names of the Phoronix Test Suite modules to load by default when running the Phoronix Test Suite. Multiple modules can be listed when delimited by a comma. Modules that load via setting an environment variable can also be specified here (i.e. FORCE_AA=8 as an option in this string to load the graphics_override module with the 8x forced anti-aliasing). The default value is toggle_screensaver, update_checker.

Installation Options

RemoveDownloadFiles:

If this option is set to TRUE, once a test has been installed the downloaded files will be removed. Enabling this option will conserve disk space and in nearly all circumstances will not result in any problems. However, if a test profile directly depends upon a file that was downloaded (as opposed to something extracted from a downloaded file during the installation process), enabling this option will cause issues. If this option is set to FALSE, the downloaded files will not be removed unless the test is uninstalled. The default value is FALSE.

SearchMediaForCache:

If this option is set to TRUE, when installing a test it will automatically look for a Phoronix Test Suite download cache on removable media that is attached and mounted on the system. On the Linux operating system, the Phoronix Test Suite looks for devices mounted within the /media/ or /Volumes/ directories. If a download cache is found (a download-cache/ folder within the drive's root directory) and a file it is looking for with matching MD5/SHA256 check-sum, the file will be automatically copied. Otherwise the standard download cache is checked. If this option is set to FALSE, removable media devices are not checked. The default value is TRUE.

SymLinkFilesFromCache:

If this option is set to TRUE, during the test installation process when a file is found in a Phoronix Test Suite download cache, instead of copying the file just provide a symbolic link to the file. Enabling this option will conserve disk space and in nearly all circumstances will not result in any issues, permitting the download cache files are always mounted during testing and are not located on removable media. If this option is set to FALSE, the files will be copied from the download cache. The default value is FALSE.

PromptForDownloadMirror:

If this option is set to TRUE, when downloading a test file the user will be prompted to select a mirror when multiple mirrors available. This option is targeted for those in remote regions or where their download speed may be greatly affected depending upon the server. If this option is set to FALSE, the Phoronix Test Suite will randomly pick a mirror. The default value is FALSE.

EnvironmentDirectory:

This option sets the directory where tests will be installed to by the Phoronix Test Suite. The full path to the directory on the local file-system should be specified, though ~ is a valid character for denoting the user's home directory. The default value is ~/.phoronix-test-suite/installed-tests/.

CacheDirectory:

This option sets the directory for the main download cache. The download cache is checked when installing a test while attempting to locate a needed test file. If the file is found in the download cache, it will not be downloaded from there instead of an Internet mirror. When running phoronix-test-suite make-download-cache, files are automatically copied to this directory. The full path to the directory should be specified, though ~ is a valid character for denoting the user's home directory. Specifying an HTTP or FTP URL is valid. The default value is ~/.phoronix-test-suite/download-cache/. Multiple cache directories can be specified as of Phoronix Test Suite 2.2 with each directory being delimited by a colon.

Testing Options

SleepTimeBetweenTests:

This option sets the time (in seconds) to sleep between running tests. The default value is 8.

SaveSystemLogs:

If this option is set to TRUE, when saving the results from a test it will also save various system details and logs to a sub-directory of the result file's location. Among the logs that will be archived include the X.Org log, dmesg, and lspci outputs. These system details may also be saved if a test suite explicitly requests this information be saved. If this option is set to FALSE, the system details / logs will not be saved by default. The default value is FALSE. When running in batch mode or using a Phoronix Certification and Qualification Suite, the logs will be saved regardless of this user setting.

SaveInstallationLogs:

If this option is set to TRUE, when saving the results from a test it will archive the complete output generated by the test during its earlier installation process. The log(s) are then saved to a sub-directory of the result file's location. If this option is set to FALSE, the full test logs will not be saved. The default value is FALSE. When running in batch mode or using a Phoronix Certification and Qualification Suite, the logs will be saved regardless of this user setting.

RemoveTestInstallOnCompletion:

If this option is set to TRUE, after a test has been completed, if that test profile is no longer present later in the test queue, the test installation will be removed from the disk. If the test is to be run at a later time, it will need to be re-installed. This is useful for embedded environments or Live CD/DVDs where the available memory (RAM) for storage may be limited.

SaveTestLogs:

If this option is set to TRUE, when saving the results from a test it will archive the complete output of each test's run generated by the application under test itself. The default value is FALSE.

ResultsDirectory:

This option sets the directory where test results will be saved by the Phoronix Test Suite. The full path to the directory on the local file-system should be specified, though ~ is a valid character for denoting the user's home directory. The default value is ~/.phoronix-test-suite/test-results/.

AlwaysUploadResultsToOpenBenchmarking:

This option defines whether test results should always be uploaded to OpenBenchmarking.org upon their completion. If this value is set to FALSE, the user will be prompted each time whether the results should be uploaded to OpenBenchmarking.org, unless running in batch mode where the value is pre-defined. The default value is FALSE.

TestResultValidation Options

DynamicRunCount:

If this option is set to TRUE, the Phoronix Test Suite will automatically increase the number of times a test is to be run if the standard deviation of the test results exceeds a predefined threshold. This option is set to TRUE by default and is designed to ensure the statistical signifiance of the test results. The run count will increase until the standard deviation falls below the threshold or when the total number of run counts exceeds twice the amount that is set to run by default from the given test profile. Under certain conditions the run count may also increase further.

LimitDynamicToTestLength:

If DynamicRunCount is set to TRUE, this option sets a limit on the maximum length per trial run that a test can execute (in minutes) for the run count to be adjusted. This option is to prevent tests that take a very long amount of time to run from consuming too much time. By default this value is set to 20 minutes.

StandardDeviationThreshold:

This option defines the overall standard deviation threshold (as a percent) for the Phoronix Test Suite to dynamically increase the run count of a test if this limit is exceeded. The default value is 3.50.

ExportResultsTo:

This option can specify a file (either the absolute path or relative if contained within ~/.phoronix-test-suite/ where a set of test results will be passed as the first argument as a string with each of the test results being delimited by a colon. If the executed script returns an exit status of 0 the results are considered valid, if the script returns an exit status of 1 the Phoronix Test Suite will request the test be run again.

Batch Mode Options

The batch mode options are only used when using either the batch-run or batch-benchmark options with the Phoronix Test Suite. This mode is designed to fully automate the operation of the Phoronix Test Suite except for areas where the user would like to be prompted. To configure the batch mode options, it is recommended to run phoronix-test-suite batch-setup instead of modifying these values by hand.

SaveResults:

If this option is set to TRUE, when running in batch mode the test results will be automatically saved.

OpenBrowser:

If this option is set to TRUE, when running in batch mode the web-browser will automatically open when displaying test results. If this option is set to FALSE, the web-browser will not be opened.

UploadResults:

If this option is set to TRUE, when running in batch mode the test results will be automatically uploaded to OpenBenchmarking.org.

PromptForTestIdentifier:

If this option is set to TRUE, when running in batch mode the user will be prompted to enter a test identifier. If this option is set to FALSE, a test identifier will be automatically generated.

PromptForTestDescription:

If this option is set to TRUE, when running in batch mode the user will be prompted to enter a test description. If this option is set to FALSE, the default test description will be used.

PromptSaveName:

If this option is set to TRUE, when running in batch mode the user will be prompted to enter a test name. If this option is set to FALSE, a test name will be automatically generated.

Networking Options

NoNetworkCommunication:

If you wish to disable network support entirely within the Phoronix Test Suite, set this option to TRUE. The default value is FALSE.

Timeout:

This is the read timeout (in seconds) for network connections. The default value is 20.

ProxyAddress:

If you wish to use a HTTP proxy server to allow the Phoronix Test Suite to communicate with OpenBenchmarking.org and other web services, enter the IP address / server name of the proxy server in this tag. If the proxy address and port tags are left empty but the http_proxy environment variable is set, the Phoronix Test Suite will attempt to use that as the proxy information.

ProxyPort:

If using a proxy server, enter the TCP port in this tag.

Copyright © 2008 - 2011 by Phoronix Media.
phoronix-test-suite/pts-core/static/scripts/root-access.sh0000755000175000017500000000070111564533734024122 0ustar michaelmichael#!/bin/sh if [ `whoami` != "root" ]; then if [ -x /usr/bin/gksudo ] && [ ! -z "$DISPLAY" ]; then ROOT="/usr/bin/gksudo --preserve-env" elif [ -x /usr/bin/kdesu ] && [ ! -z "$DISPLAY" ]; then ROOT="/usr/bin/kdesu" elif [ -x /usr/bin/sudo ]; then ROOT="/usr/bin/sudo" fi else ROOT="" fi TMPRUN=`mktemp` echo "#!/bin/sh\n\n$@" > $TMPRUN chmod +x $TMPRUN echo "\nThis test requires root access to run.\n" 1>&2 $ROOT $TMPRUN rm -f $TMPRUN phoronix-test-suite/pts-core/static/scripts/build-package-rpm.php0000644000175000017500000000720411564542013025331 0ustar michaelmichael. */ if(!is_file("phoronix-test-suite") || !is_dir("pts/") || !is_dir("pts-core/")) { echo "\nYou must run this script from the root directory of the phoronix-test-suite/ folder!\n"; echo "Example: php5 pts-core/scripts/package-build-rpm.php\n"; exit(0); } @require("pts-core/pts-core.php"); if(!defined("PTS_VERSION")) { echo "\nERROR: The Phoronix Test Suite version wasn't found!\n"; exit(0); } shell_exec("rm -rf /tmp/pts-rpm-builder/"); shell_exec("mkdir -p /tmp/pts-rpm-builder/{BUILD,RPMS,S{OURCE,PEC,RPM}S,phoronix-test-suite-" . PTS_VERSION . "}"); shell_exec("cp -R ./ /tmp/pts-rpm-builder/phoronix-test-suite-" . PTS_VERSION . "/"); shell_exec("tar --exclude=.git -C /tmp/pts-rpm-builder/ -cjvf /tmp/pts-rpm-builder/SOURCES/phoronix-test-suite-" . PTS_VERSION . ".tar.bz2 phoronix-test-suite-" . PTS_VERSION . "/"); $spec_file = "Summary: A Comprehensive Linux Benchmarking System\n"; $spec_file .= "Name: phoronix-test-suite\n"; $spec_file .= "Version: " . PTS_VERSION . "\n"; $spec_file .= "Release: 1\n"; $spec_file .= "License: GPL\n"; $spec_file .= "Group: Utilities\n"; $spec_file .= "URL: http://www.phoronix-test-suite.com/\n"; $spec_file .= "Source: phoronix-test-suite-" . PTS_VERSION . ".tar.bz2\n"; $spec_file .= "Packager: Phoronix Media \n"; $spec_file .= "Requires: php-cli, php-gd\n"; $spec_file .= "BuildArch: noarch\n"; $spec_file .= "BuildRoot: %{_tmppath}/%{name}-%{version}-root\n"; $spec_file .= "%description\n"; $spec_file .= @file_get_contents("pts-core/static/short-description.txt") . "\n"; $spec_file .= "%prep\n"; $spec_file .= "%setup -q\n"; $spec_file .= "%build\n"; $spec_file .= "%install\n"; $spec_file .= "rm -rf %{buildroot}\n"; $spec_file .= "./install-sh %{buildroot}/usr\n"; $spec_file .= "sed -i 's|%buildroot||g' %buildroot%_bindir/phoronix-test-suite\n"; $spec_file .= "%clean\n"; $spec_file .= "rm -rf %{buildroot}\n"; $spec_file .= "%files\n"; $spec_file .= "%{_bindir}/phoronix-test-suite\n"; $spec_file .= "%{_datadir}/phoronix-test-suite/*\n"; $spec_file .= "%{_datadir}/doc/*\n"; $spec_file .= "%changelog\n"; $spec_file .= "* Fri Jun 06 2008 Andrew Schofield \n"; $spec_file .= "- Initial release."; file_put_contents("/tmp/pts-rpm-builder/SPECS/pts.spec", $spec_file); shell_exec("mv -f " . pts_client::user_home_directory() . ".rpmmacros /tmp/pts-rpm-builder"); file_put_contents(pts_client::user_home_directory() .".rpmmacros", "%_topdir /tmp/pts-rpm-builder"); shell_exec("rpmbuild -ba --verbose /tmp/pts-rpm-builder/SPECS/pts.spec"); shell_exec("cp /tmp/pts-rpm-builder/RPMS/noarch/phoronix-test-suite-" . PTS_VERSION . "-1.noarch.rpm ./"); shell_exec("rm -f " . pts_client::user_home_directory() . "/.rpmmacros"); shell_exec("mv -f /tmp/pts-rpm-builder/.rpmmacros " . pts_client::user_home_directory()); shell_exec("rm -rf /tmp/pts-rpm-builder"); ?> phoronix-test-suite/pts-core/static/scripts/build-package-deb.php0000644000175000017500000000531712202614615025266 0ustar michaelmichael. */ if(!is_executable("phoronix-test-suite") || !is_dir("pts-core/")) { echo "\nYou must run this script from the root directory of the phoronix-test-suite/ folder!\n"; echo "Example: php5 pts-core/static/scripts/package-build-deb.php\n"; exit(0); } @require("pts-core/pts-core.php"); if(!defined("PTS_VERSION")) { echo "\nERROR: The Phoronix Test Suite version wasn't found!\n"; exit(0); } shell_exec("rm -rf /tmp/pts-deb-builder/"); shell_exec("mkdir -p /tmp/pts-deb-builder/DEBIAN/"); shell_exec("mkdir -p /tmp/pts-deb-builder/usr/"); shell_exec("./install-sh /tmp/pts-deb-builder/usr"); $pts_version = str_replace("a", "~a", str_replace("b", "~b", PTS_VERSION)); // Fix version $phoronix_test_suite_bin = file_get_contents("phoronix-test-suite"); $phoronix_test_suite_bin = str_replace("export PTS_DIR=`pwd`", "export PTS_DIR='/usr/share/phoronix-test-suite/'", $phoronix_test_suite_bin); file_put_contents("/tmp/pts-deb-builder/usr/bin/phoronix-test-suite", $phoronix_test_suite_bin); shell_exec("chmod +x /tmp/pts-deb-builder/usr/bin/phoronix-test-suite"); $control_file = "Package: phoronix-test-suite\n"; $control_file .= "Version: " . $pts_version . "\n"; $control_file .= "Section: Utilities\n"; $control_file .= "Priority: optional\n"; $control_file .= "Architecture: all\n"; $control_file .= "Depends: php5-cli, php5-gd, php5-json\n"; $control_file .= "Recommends: build-essential\n"; $control_file .= "Maintainer: Phoronix Media \n"; $control_file .= "Description: An Automated, Open-Source Testing Framework\n " . @str_replace("\n", " ", file_get_contents('pts-core/static/short-description.txt')) . "\n"; $control_file .= "Homepage: http://www.phoronix-test-suite.com/ \n"; file_put_contents("/tmp/pts-deb-builder/DEBIAN/control", $control_file); shell_exec("dpkg --build /tmp/pts-deb-builder ../phoronix-test-suite_" . $pts_version . "_all.deb"); shell_exec("rm -rf /tmp/pts-deb-builder"); ?> phoronix-test-suite/pts-core/static/examples/apt-full-upgrade0000755000175000017500000000042511367314633024566 0ustar michaelmichael#!/bin/sh # Example script for Phoromatic Ubuntu Tracker # Toss into /etc/ echo "Dpkg::Options {\"--force-confnew\"; };" > /etc/apt/apt.conf.d/local-dpkg-forceconf export DEBIAN_FRONTEND=noninteractive apt-get update && sudo apt-get -y --ignore-missing dist-upgrade && reboot phoronix-test-suite/pts-core/static/examples/phoromatic-tracker-update-kernel0000755000175000017500000000071711344512424027746 0ustar michaelmichael#!/bin/sh # Example script for Phoromatic Kernel Tracker # http://kernel-tracker.phoromatic.com/ # Toss into /etc/ and is called by update-kernel-from-ubuntu-daily-ppa script on cron job when appropriate mkdir /tmp/kernel-ppa cd /tmp/kernel-ppa wget -r --no-parent -nd http://kernel.ubuntu.com/~kernel-ppa/mainline/daily/current/ sleep 1 dpkg -i --force-confnew --force-overwrite linux-image-*_amd64.deb sleep 10 update-grub cd / rm -rf /tmp/kernel-ppa reboot phoronix-test-suite/pts-core/static/examples/phoromatic-cron-starter0000755000175000017500000000047211344527262026204 0ustar michaelmichael#!/bin/sh # PTS Phoromatic is hopefully running since startup, but otherwise try running it to recover it. # PTS Phoromatic will automatically quit if it can't secure the lock meaning it's already running # Toss this into /etc/cron.hourly/ DISPLAY=:0 phoronix-test-suite phoromatic.start >> /tmp/phoromatic-output phoronix-test-suite/pts-core/static/examples/phoromatic-init-starter0000755000175000017500000000072311344527267026212 0ustar michaelmichael#!/bin/sh # /etc/init.d/phoromatic-init-starter # update-rc.d phoromatic-init-starter defaults case "$1" in start) echo "Starting Phoromatic" rm -f /tmp/phoromatic-output DISPLAY=:0 phoronix-test-suite phoromatic.start >> /tmp/phoromatic-output ;; stop) echo "Stopping Phoromatic" touch /root/.phoronix-test-suite/halt-testing ;; *) echo "Usage: /etc/init.d/phoromatic-init-starter {start|stop}" exit 1 ;; esac exit 0 phoronix-test-suite/pts-core/static/examples/update-ubuntu-aptitude-full0000755000175000017500000000037011367311565026774 0ustar michaelmichael#!/bin/sh # Example script for Phoromatic Ubuntu Tracker # http://ubuntu-tracker.phoromatic.com/ # Toss into /etc/cron.hourly/ hour=`date +%k` # hour=2 if [ $hour -ne 2 ] ; then exit fi /etc/apt-full-upgrade > /tmp/aptitude-output 2>&1 phoronix-test-suite/pts-core/static/examples/update-kernel-from-ubuntu-daily-ppa0000755000175000017500000000041211364440301030275 0ustar michaelmichael#!/bin/sh # Example script for Phoromatic Kernel Tracker # http://kernel-tracker.phoromatic.com/ # Toss into /etc/cron.hourly/ hour=`date +%k` # hour=7 if [ $hour -ne 7 ] ; then exit fi /etc/phoromatic-tracker-update-kernel > /tmp/update-kernel-log 2>&1 phoronix-test-suite/pts-core/static/images/pts-80x42.png0000644000175000017500000000344111726024454023214 0ustar michaelmichael‰PNG  IHDRP*$¨Ü sRGB®ÎébKGDÿÿÿ ½§“ pHYsJJŽØ°*tIMEÚ Ú¬rÜ¡IDAThÞíšyˆÕUÇ?ßYiR§²ÝÌÜÊ2¥)i+Úˆ(C l1Å(-2 Š Ú‰²…0…6‹¤È¬¤’Ð"³M[l#£EÆD’p)•œF§qN¼óËËí÷fÞ{¾7JÎ÷ýÎï.ç~ï9çž{îƒÒÓÝÀªàYÏÿˆ*:aŒz 7ÿSª`7§qãÆô XU3gΜÞ`î4 ¸ âå `Y~;F]vØ`€»3å² ïíq\_ÿ½øÅƒâ;AæÀàH :϶^Þé ‡¯ýýÝ\€¤ø ,ïàúŸûF2äKÅ0̈́뀟œ~Ñê >øX T–¼À  WŠ »”üée.‚&ßšƒ “z wPë:ÅäÚ”« ie°Øø+‡ö•,L‹ÿ~6+ù½h+À¶– ÀÆ,‚®î¦mnnzõÿ¸ÒýT{À[² ò½8eÑN>,¥f Ê37w”¼¯RxŸ”j¹Á5&Û.V Ô¤ªÉ÷#²´ 4'Î<9uÜëO‹/` ™Lxc¤µÍ̱& ÿéRØÍŸ|ÕÈ3]+³Ñ)ÀçÀqY‚ݪ²65EÒÈ€¿wN¶OÊŽ›FÃG H,‹I‰±3 '~kòª<Úßì|P`–¦PšœSìdBL+É~˶Íz‹÷}.4˱–ÌeQO?Å4¹Äªõ+¾2}’íiþ|h5°Ä3@M)ßëÂ̳¤°ÜÔû;qmIý¤®Eσì&4~üøTþÈ‘#ó6Çð™JÏJŠÕºÓ(Ûx…ÈQ*Ù˲ V%i‘¤…Àx3CÒÒÐW  #$Ëj™qgHúXÒ®ð>VxxМ&©ÕùÖ)^ëáOàJàmOl4›Y›¤Ï½î·Qò`°HÒ3d.¼’ly‹ÙêåÀÉf¶DÒ?Õ—™Ùâ\\jf“Ä›£DÀ:`çè ƒpyþL9–Å}„ Œu=Õ̾îÀíl®3³ðþ¦Ÿ¤§$5y¼§xç'éWתÄ·sLm®6³ ‰„–Q‘·ùäÖFf´:¦x xËMh¾™5IZlsÐÇHZà«<*êc³ó·$õªÌl‚¤Ù’æšY|²ù50áÛ€9’¥À·dþnR|æÚv—¤%fö¡·ãæÙ˜ä‹¶EÒ,ï»Õçö—™5Jê/é2÷æ/KúøØÌÞ…úd¥ßŽ’ð^IEND®B`‚phoronix-test-suite/pts-core/static/images/openbenchmarking.png0000644000175000017500000000260311564533734025142 0ustar michaelmichael‰PNG  IHDR@@ªiqÞsRGB®ÎébKGDÿÿÿ ½§“ pHYs””G2QtIMEÚ .$H4FIDATxÚí™]L“WÇÿÏ9ï6ißòmÌ6è¼Z´ÅÝuºŒ¡pKvcñ#B4¨SÑøc²¹mñc*Óa)ÄãmKËõŒ’…í~»›sÙîheË°ï³ PBÛ÷«•'éÍ9ÏùøÿrzÎó«gP¡Ö»îòRKÄëÍ^|Ö„Z¯•eæA¨ÿšNAwÖAŒ„Úª•¨(+1\|M©DG?ñº%CRl¬ò ¢4-‰éß‚ìÃR‰ ·¯ëwê6Wyðö ŒAhu ª06Ÿó%ƈ׽ "…À¦ù!ü p:†ÑP4 MÔMµÍnJ$BUxàŒC÷iŸAx«¤x¶îqªÃÑúGÏ[>-|u`Œ¿è¼Þ`ñ†xáã÷¼/Bq=:7?ü߀O Bjõÿ…ð~±D_U–œk6ýÔIðâÍâ"H‚Ñ€#õæŽiKZ€äÚb‰¾UÆ‹2(aµŽ$9ÿ§©~úýχ?{wAß¾üùïËä×™ÞÖ*ÕÌÂ"ÃL[’HÔ}ß½ÌéñØäàLwL˜UÍq2kƒ-#­ŸËá—±Éõ$i0ñ¶¼f1• EÛ¾ŸX÷bÇoc“네(ªÙy…Ùõm³ „3¶U¸”û¦ÞAŸã1í°BŠn—rÏ’K0¸Ú1@ÄÍ4 ÄkšÝjæ_…uy‚>õ3ï2‚FÀ®JU¹c‹g0´Z½ÅÄ­&AÐh­P•[¶ŠB>µŒ¶©ɸ׎ mnUé·e Ô»ÚÐn¡ÝíTB¶Ž{«A"ìÑÑžJ§̉P8èsöСã¹ï¨pÊžœÊ‚ÕÎëDاƒø}n—¼ž“ÉPÐçìfÐ,þ·KvÃ`34 U;®2Ñ¡ òC•.y5/ÒáÏq™Ai\÷ª¼œWõ€Pµã"ÀG þ¨[•ó² Ò[­v|ü%ÿ¸[•]¶/ˆd á<À'gùÏŸ¬Tåy¼*Ö:’<Õ:’ä_ÇŸòãdꔕ{ùæâ”)èçÿ‚©PàSoÆ‹ÚU½6žV ïÅ[ZÏ jv,O?L+p@L+p@L+p@L+p@ô² ·1s0 ÿÀf<ˆ}“7´Žx^‰…xvöwáÞ¦ÓM'áƒx ž_ñ|+n[þƦÔ³p5Þg çßT`Õ> 7c-Þ£Zy0Àïñu13& 'ã8Ï`Êk©çã>»¶z”ÑÆ…â«ÙÜÐþ‡ƒ°\˜§Ê <«qTMY/Ç/ñ‚A•à3xiÃ2Ca RÁ³?Ã<Œã„?³‚XØÅ×c´K¿ìal‹s¾·%ôQ|ßÄHrRdY¶)¹®©j?„CqY…n—â|ìì û­"ÿBųË1£ï{tí®äö‚áä:¬ŠiH¤sÒt®é±£Oc]B›ƒÓ{il Ø27 ·1´ñ† ú…}ÈÍù×$ô%XÙ¡Íêä>–_á˜ý4áfõjÿŒ]=ðÕB[l e<’wÚÖb»pv ß…Q²—ãs¥ÿ-áf[Í>û°?¦¥“Iª…!¼0¡ý®¦¬t¦rëâ‹X?@û!áß^"œñ&LË8áÏKhýξÿLþ˜ßŸ¨àíÝTaT„o×T‚Ã…»vÌþ{ʼnGÝ2Ý+’ÿ[óû– Þú”½ Dȸ§Ï¶)Ä·56U™…—$´Mù½jF/À=}öñ8.îÕqâ#ÇðQ|¾LhJ3q&ÿ$¿ßƒÝÆ–4a®Wow|÷çW/¸ND3·$ô“õ¯À¶Ä¿m"¡ºIh{qGþû ü4y~¸Ø¦ +°#¡-hBð  | n5Ñž|K$] \nbòõ",qødc.NhU¶¹oÔQ`[d^– ‡x8y¾K(¬Œû…ã[FKÌÜõ"Ï7ßäÔ©Ç—+èk›^5àwâuøgàXãíYYÞ~sų¥bÙ,Lèóðü÷ü+ÿ}ªðÛ <Ú¡Ïnh©N¯íÁ¯jÈ›€*ÎQ/y¹Æžï»áqbž"Ó]5¶ÙšÃ§ð×&5U•Û.”sõ~ø¶»ùý†ú­ƒUª—t- ªÀQá&ÌÃzló8ÎKô¾ûïOâ"ÜX5±j ¨¶a„¶åÏW ¥¥!\¯¸¯u”³„#>ÇX©2u;VÔè#Ã_ÄFõkÕNývcQS©Ÿ¹Id‡Æñ¶²,ÛküLü.­1ا%¦O& ˆiˆNŽëLá’ì†þn»¾¯áþ‡q„°Oð.ãk#;pe¾†ÄI‹aܦútÂñÎö#´ 3Ezê6Q4*^´ebèU‘ŠŒÇsóû3þ;ñw áàP2®•"uz~_žÓÓÀ¾(‡ØÏ7~‚,µŸËDÖ½<Þv>®mbSœ'¢¤v‰¯œÍ×i'ì»Ö^ñUÁ×D’àH¼H¤É?‹ò6×ç×™¢Xõ=|äÏS’1W„„ç'ùN¡ð›JŠ vÉGñŸü>" í7ãZ1k1ùR‘Z[""¢E%9õ”£ð7Qe+ÂË+ð2œ!Ò\oÄÙù;œ("¥Tø»)ð¤¼á•ùÀGŸUÖÏË…~H¸ÅAí+Dêèq¶æÝÆŠT…Œ[Œé6çýÜ+\£m]ÆE|-b¶,Š?X¤Ð¶ gù‡ù½ÀBÁ7 §¿V‰S·‹ó?ˆÿM)c·à}H¥Ø!Pd¬÷˶Jô]¥ç ǵ±ÏÄüábI÷r&gDÌæ5"]¶oÇW„23Õ“ã±:VŠaÁSUó-žˆZôC"‡A²ËÅX$¾zê¤.©óÝbÙvñ"ÁyšXÞëu?þñ]|\¬’ âå.¶{«xéKñ[c›ÅÙ®·…Yfé:aNÊØ(–îù;^œ¿ã:I©ö¿.öT£Y8¹RIEND®B`‚phoronix-test-suite/pts-core/static/images/pts-77x40-white.png0000644000175000017500000000232611726023663024340 0ustar michaelmichael‰PNG  IHDRM(»0wYsBIT|dˆ pHYs††|ûzhtEXtSoftwarewww.inkscape.org›î<SIDAThíÙ[¨UÇñÇS¤r5ÓYDQ–e]¤²ä€a¾D b ‚ˆòÁ (ºIP•½˜©Q”A…VàƒT™Ý­PÃÔ¤HÏêaͶiöì³gÏ̱Àý…aïùÏZÿµæ·×åÿ_{DÁ0²·§îwãªálðhÐ;Ìþ'czêþçanï¨0Ü¢ý_éÃÛ|T¤ò±*ÚÜ™±mSP´žÚ»s Э]ÑJЭ]ÑJ0Ôî9b¦¡?±íwšõøÃ'ŒÆbÌJú4±„ËðYi%ÚÕxç´x>w‹âÝ' 8\\ŠqzE?#kè š§ç(¼‚·´,ÍYX'ŠÖWW§RLÇ{ª V+iÑúð–ð3O 'ÔÑ©„ã±ÇÕè³Ó³Gaµ(÷¸~ âbœ!®oi¦a-fãP ?cq›>íÀ ¸çežÀËØÞÆG?•¨“KC´Eâ:•åm,_$M?VŠ#,Íbzòx‹öú°¼MŸ6‹¢]±ÌÀ×mêWa!f¦îw㡦R!„1!„¡™¥!m®Å9õö„Æ&Ï—åPßq÷ÌÌ}#øüªEÙ/:ô¿>¹Æ‹ïø6åGŠqç âˆo°Tûà:Ë1^=B¢ÍOÒ¼™|nG[zg].fÙ©[„½bªW„×’öŸHÙ&à4q&”¦êyZŸ«eY“|†Ô÷SñhÅv‹²!ÇvvU§UD›Mšw¥uøÀpOy÷r¤5#ÛÒhG~h +ê³gÏþ®¤ÁË3™Ìò¥K—n(†f;£ÒÁÔL&3ÆSþ' (Fµ‹¾6‚vFµ´3ª QmíŒj#hgTA;£Ú µ£ºc0·O/ xxØlKttÉâCÀ4àtlü уÍAªÈ‡QÀW€™À9@§˜¶ÿîn^,up ¡ø6¡qc/ßLfĉ¾,0 Ø ü˜Dó:¸[]·b“Ô’8x¸œt˜T6„Õ ØüèWÝÎÀ<`0¹¸¡•ŒëZ¨ÿDácÔ(à/Àøèw~ |+Z… 3ð k™ûM ÷¨aÀ£$ ê,ê€%H7s€&Þë¶Œ(£Ž y&íÅDÊKÀ{˜5ÙÌ}‹±ýn]žc»(šQlV¹ë91íVï@;{¢‹(£n>Ó¶¸ø=Pï©\ |ÿÆÝXéÚ½•ÇØ>î>…`ÐÛŸ|˜ü¸@š‰¢ªªªÛáÇ}«ýHuuõs¡ûr{Ô©˜ Âu˜ýô;üLxø:¶·í ´é\ÓO8)Pþ2-Ì$€C‡¯¯¯ÆóYw_ŽQ7Öç×ùfÁÔ`Ì ‰„y@ï\b¿{€qÀÓ%Òi30;3U”#Â2@_wß!ã8 _ÝËÀXÌc²/z!|›”½ôigÊFêrbiw þ<ìE yBòÅa`ðC,>5÷…ÚT}ܘ+F`¶áXY£FÚ„g;J›Q³åÿÀÞv0íîM7åJÌhÙb…¢SÛŸ,FWàA`‚§n&ɈÀ¡x­4E_oÂaêû"×û çcß@r¹ Ià]Ì¥æÃpR4¦ÓbT'L:ÖS'àîFe+t†?Mp\I`&£)žéJƒQÝ0;&¢XMSÛj%ð·@ûYÀ/h=~º~øm§:L:¤‚¤5óžOÔ×b1­Æ¨®Š¡{ ¦fª¤Ñ•Ž æ‘ðáEÂ6aɈS&Nÿģ¨ÀÔÒ‘ÀTšwÍ,Äœ¦>< ü øF þ,ÿâ,.¶3ÊsöÞ.,×#Š1[* ôÁ†kê„úñ"ŽQÕ ÷u÷ŠÃXÞÆ'cÚ .ó”ßFSF¥é~˜ê±\ÆÔP®”æ1wKs¨>‹©ìm wœoÔ‹r0êfà3Àûy¶ÿ¶×°l Ô`’ U¤É¨Àù˜’P¨w¡³W¦ÑºóÙ7bžôƒiw”£žÃö˜È+a‰7_ž twRRØ|KóEEœ2±•æZÞܪ¹Ók kuÅ¢‹û,ÁÜJ“1bo,Jœ³ižõÜû*Éhc¹ï«XŠÁìÙ F6›­“äÛbéÅ1j4æÐlMØKØ‹áÃf÷)+***&I§HZ.iº¤Ó%M””qmÔOÒ…’FEÊzJú¨¤Á’ÎreÝ%/i‚ë I]$UIê*i†¤¾\?ýÑ&©äwôs¼¤½žòÁ’¦Iê);Öõ9Ãõ3PÒ.I—º>¢÷ÏôkÝS%UºëJI##s2\Ò1’–¹ù;;2¯ã% <’ Ú£†boW.ÇárÌw .”qت닭€k#åwßÇ‚k½1v$ðe,â›ÅDį€;1O|5 q¨Õ˜Íô¶«e*­Â"¯ùâìÈëlµuÀ›ܸ†¹ß9q5[AQlÆNf.àè8Ù•X^˜ÔÉ¥„OÁB51[°ÒÑsTs³Ýu+ê-IKÚ-i¦ãðrIóÝõtI÷ºëû%ÍŠ¬¢wÝ[;CÒúÈ2_Òm‘ßÏK:CR·zºò'"«gVÞi’vJZ+iJÌ›è[Që$Í•­ìu’Ƹ1¾"é-ž–tr€v/IJú«¤!®l…¤©îúÓ’Ö¸ëK$-r× $-t×pó;έ¨¥¬¨7ÝÛpGç:ä]¡a¯Hƒoî à iTÑc/Ñv¸ëœÜÞKC®_-þ}t«k3;XWzc ÒdL!ªuÏ0 Û‹7Ї=À¹XŒlYcÈ¡ 6Nr´VâO_È‹Qïc®“|Pƒ‰hHóKª>á®;c‡žÉ³°<ºÇ0ñé‹ÇáL{¼Þ}žÂDÝ6l²ö`ö¢ù”‰œ¸æÌ%µ>è~ûG€9ps4wcÿÍqGd<|7%.v ö†MÀVàEøÕéeؤlÆì,bÛ'>ÎÄdþ¹ØžµK{$Ï1ÞŽ'cŒ¸cÖCn 'л ·ÜÈч&¾„9Š·c+t¡+_E©çb/ÑOÿkipV_ Ìw´·aù&³ð$‹þ tX’*£oùIEND®B`‚phoronix-test-suite/pts-core/static/images/pts-308x160-t.png0000644000175000017500000001777711266667445023656 0ustar michaelmichael‰PNG  IHDR4 ‚~sBIT|dˆ pHYs  ¹ô-`tEXtSoftwarewww.inkscape.org›î<|IDATxœíw¸UµÀk%Ò„^‚@Aà£141D¤H—¦ˆt*MAŠOé ¨)@:Jyðé E½Hè%B€@`¯÷ÇÞ×;99í޳ϙsæîß÷ÍwçÎìY{sfÖì²ÖÚbf$ZˆLækPÌEfö“ú$E Þ ôa†…­ÅP$‘( š·‰D"‹dЉDaH-‘H†dЉDaH-‘H†dЉDaH-‘H†ä‡–H”ÝvÛm>`TQïžþùS"Èi:É %Åe}àŠr.vŽ §é¤.g"‘( É %‰Â Z"‘( É %‰Â Z"‘( É %‰Â Z"‘( É %‰Â Z"‘( É %‰Â Z"‘( É %‰Â Z"‘( É %‰Â Z"‘( É %‰Â Z"‘( É %‰Â Z"‘( É %‰Â Z"‘( É %‰Â Z"‘( É %‰ÂÐ ‹ˆƒ!x#<˜nf.WŹ!"ó£eùð÷Æ Š÷’~ÅÌÎÉ[‰N¡m šˆ ÆËÑ}£Ž†ã™”¹æ`ððð|ø;ÑÌ^mæ‰V "ýïâW_._ZÆý@2hu’›A‘9€uñÀzÀj@¿Š¶…5JäOnÛ­föA£:'ZˆŒövÊYD›Órƒ&"+»âoÐù›XÕ2aÛ ˜!"×çÿ03kb½‰ˆÈhàh`{zþ¢KôQZ2Þ "Ddg™<ü„æ³RæÂÐ;€É"r¨ˆ maý‰:‘!"r ð$þ7KÆ,Q7M5h"2HD¦_kf}u²4ðkà9VDZiXU‘±xCöS`@Îê$:¦4é'"û¯§#šQOƒÌ …7lNjȠ¼êˈÈO€{€%sV%ÑÁD7h"²&08‹Öv+{Ë à`’ˆl“·2}9 øm4ëžèL¢´0öq>p/°J,¹-dð¹MDÚ±EYHDätà°¼õHƒ(MDVÁÏ^Îæ/ÖaŒ‘ÍòV¤èˆÈQÀyë‘( 4Ùïü7ªquÚ†áÀõ"òIƒÓM@D¶ŽÍ[D±èµA ÿ€3€9ã©ÔVÜ,"sç­H‘‘%€ òÖ#Qnb=ÎJÄûf›˜Ùí‘ä% DÅIü°‰uÏÄG,mf{ôÖ˜•ÃÌž7³Ã%€ƒ÷bÉ.ÃÀ/š(¿¬QÖɘ%*Q¶…òýŸÝÄzïö3³gšXf6ø­ˆü 8ŸŽ»9à‘?™Ù³M]–$ç&3»4’¬D/3fÌšøVw£Ü=qâĨ6 R—óPš³ªÎÀáfvZdW$ ï#"×— D®bð{üb/‰Ù‰5lq\$9‰ÆØŸF¿QöÆ›Gc¶ÖŠˆ §9þBïë¶Ú˜e1³Ûð«K=ÒñãD$…ô”g‘2Þòš|Itåº_±yX+ÇÙÀÿbf¯ãÎïn‚øŸ7AfAÆ#iµ®D-f1h"2/°ä:ºŒÙäÈr{™MÃ/X{GdÑãDä‘eÁd¼AF¢à”¶Ðb†ô¼l`fS#ÊŒ‚™} l†ON“Þ3;_FQÔœ{‰ˆü× çǘáM_[µSˬ”à;¶ ðjD±›‰H Àž•édćKœl m=âÞ4GšÙ?#Êk fö`;¼_\ øQ$YEaZcEd`9‰“5h;D”{ùÄö 3ûpbD‘»D”Ub´€[D“(0 ÿMܸU$™_ûtàŒÔIø…‘c0JDÖŠ$«¼IΑah$‘(K×ͱñ&Î5³§"Éja’ ¦ÛEJ-ÔÍÓ‘ä¬ü*’¬Dé2hߊ$ï3|K§Sù >%M ’“m71}þŽ‘=#ÊKˆ.ƒ6.’¼ ÌìH²ZŽ™} ÄŠdXYDb‡Xu$fö ñºóœ'"çŠH«sà%Úœþ"2ˆ•$pB$9yr p {· ðmàŠ†5ªÌ+ÀcM”ßSª›^‹÷sŒÅ^Àö"Ò•?ï%àß´OÆZ>¦™ÙŒ¼•é+ôV¦ÎTÜ5xÖÌš#ÙRÌlºˆ\ŽÏ¥Ö(«Ó\ƒv«™íÑDù1¹œ¸ `Þw²­ÓÃ‹È `2>ûò£ø•‰õ&0MÔ£"ɺ>’œvàÊHrFG’Óñ˜ÙDÚ«5ÙJæV¶Æ§±ºxODΑ•sÕ¬`(kñÜ{"ÉiîÃw%V°¢pLÞ ´Ãðés‘{EdËä’Ò81[hmP/föqRÕ,’e&<×ÑœÔMÎZø1ÆgDd£¼•édX2‚œ7ÍìÃrÚ‰'#Èè‡OÑà¿k?ìCõɃ¾Ìhàï"r½ˆ,”·2ˆÇ¡ö…2ÚI‘ä ‹$§˜ÙÀyyëÑæl„ilØb?o»‹ÈI¸ÂZ9–þ·Q!É • "ƒ€ïGwo¥!3î£À˜ëèwy8§A9Exˆß[Û#" G?&Ž3;ø™øowE’×ñ´ÓÛ¬]Øž8HfRûF‹µÒ¾¡Å’hSÌlª™í|‡¸ãD”Õñ$ƒ–!…X¡8÷‡ ìjÄz³®lIV¢‰˜ÙÀF@¬…SÆG’S’A›•M€å#ɺ­Ž2÷àWšÁÿˆH¬®L¢‰„õb½8WI¿{7É Ddqg ¯©UÀÌÞÇ/Áƒ•ð9êÁ€ç#È™ƒxQ-O2hÝ|5’¬‡Ìì™:Ë^©N€cÃàs¢Í ³¶—Ek]Ž'4@D–#îŠDõ ìuÄË'7ð§4AÐ1ÜIÎðHr:ž>oÐB,䟉ç¤ù9=X\ØÌ>¡ŽîiØ88¢¼Dóˆår’Ö­ôiƒZ2'n³‹+Ìì?=¼æ×Ä] édÙ$¢¼Dsˆ€_˜Ò§ pñœhÁ¥O,˜ÙÓÀÕõè\)"c#ÊLÄg¾Hr¦E’ÓñôIƒ&žßE}½™=ÛËk!n+m0p»ˆlQf".±RTmMÜ^Óç ZȤq9ñ4(‚°¯Š¨ øqÁkEäés¿uËËÿõHr:ž>u“‹È(à_øð¦Ø\cf6(ã⯠¥ÀñøÖڈȲ½DD$ÞpGµ$}Š>aÐDDCú™‡ñùµbó Z|fö:ðˆµ)Ï·€gEä0™£Iu$êçâ,!ùv/&¡ Ká šˆ|x8“8«Ä—ã83«”™¶§œ<IV)ƒ“€§EdIÙVr@DvŠ$îžHr A! šˆô‘Eä.|ø×šXÝ$üli‚ùnx¶f± pð‚ˆ%"…Yl¥‘9ÂdÔo#ŠýGDYOa šˆ ‘Dä ¼Ãâ ø\QÍd°½™E5>!xùg1eV`IàX`²ˆ<,"§ŠÈf"²D xއˆ, "»á_~1'£ Ÿ'±ºËŠÈ‘dÕ¢?~ìa0ßÚÃlµ>ÈÌo†`3;]DÆ­r»X-l]Y fŠÈëøU«>¦¾•Þ7®²†BEDd%ü˜RÑèÊX;hF8Úmföräv,± ÚÖaëK\efç6¹Ž]ðK5¹žr õö¤îÞ>´ó‘ö†?æ­@»Q˜.g‹yصٕ„ôBßÞnv]‰ŽãEàÚ¼•h7’Aë9“ñ]«Øþbe ‹ïnHòOÌÊ)föeÞJ´É õŒ· ÌìVVjf›‘VOx&ág©%$ƒV?oë›Ù‹yTnfwãÇ™RK-±Ÿ™ÍÌ[‰v$´úxXÓÌžÌS 3»¿ÈîÔ<õHäÊ3»=o%Ú•dÐjó °V»L7‘µñcy‰¾Å“øTñ‰ $ƒVK€qí¶*¹™MÁG?ü%o]-ã`K3Kã¨UH­<3€=ÍìG!EvÛafÓÌl;üJO±ÖxL´'Óñ3ëSòV¤ÝImv&k˜YG8-çÞÕòÖ%Ñ>62³‡óV¤H­›O£€•ƒ›DÇ&+ÖÄ·Ö>ÈYD<^Ö6³{óV¤SHÍó7`3;>v y«03Zk£ó‰·"{"nV ëM$꤯´[€uÌlS3{)oeb`fï˜ÙîÀ²À ù+uû›šÙ¿óV¦Óè‹Íá[dcÍlƒ¢6çÍì%3ÛoØ~GŠmwp)°œ™ýÞÌb.˜ÓgèKíiàpà+¡EÖ'ÑÍìe3;X ظŒøë$zÏÀ•ÀŠf¶£™%§é(r æOû;ÌìÑœõÉ•È|p“ˆ Æà`® ¬Ì£z}Oû€kði¨ÚÊϱ“)‚AsÀ«xÏùÂö0ð€™}–§bíJˆ¼?l'‡äÅ'˶ñ ‡„¿ƒ¨ï¬·Ý¤é@Se戟á?Û4àeü½ùðP§N>µ;± ÚùÀY‘dÕb&>{êÇaû´7YRÝ„ñš7ÂvWõ?¬ÒêzÅ#–A{»Ó|·‰>À=À–ä¼Zòÿ¡øñèFÉÎÀ¿D]…Þw²œ`fGF“H$½¦/Ír&‰‚“ Z"‘( É %‰Â Z"‘( É %‰Â Z"‘( É %‰Â Z"‘( É %‰Â Z"‘( mkÐTu´ª>¶V•H$jÒ´ôAª:øn™S_âÓ©|<眫”úz °rØ¿?¾†} UÝX<ü;Á9×ò5TuO‰þÇ9WØõHUuu`àëÀÂøÌ2o/⟃»œsO6±þoãÓH\êœë¨d Í̇¶pN­Bªú2p”sî²&ê’€ñaÿòYDål _ƒ2ž¢  ,«êIÀϘ=ïÜRÀXàø¼qÍLµ´°mØÿ;–ݸU ?^Á¿çÀ' X¸TUçvÎÕ4€‰Žæ1*ßs‹âï ðyÙ*eq[©v@U ÿ~€o <Žf–6¾‘vC« ÚMιïwý£ªýñ©Ÿ/Æßȧ¨ê%ÖÄí NÁ/Â>“jËqΩtNUO ÿžèœû}k´êªº ðüýûOçÜA Èü*üû9°Šsî•’b'¨êH|ºôfr6pcØŸmÕ)U],”Y¸Ý9#/Z4rIÁÆonWÕ5ç€9ñ©ž7®ÊC§¢ãœ»%o ÆP`ó°ÿ|ƒ²6 ò®,cÌpÎM¦4XWUœswQ=kñ<øÖ"´aÚô\g9×]â~éz®SUQÕªºHoêUÕ9Uu¤ª~EUôFF‰¼ùUõ«ªZu|HU‡©êrªºªÖÊÏ_O½CTu”ªÎѨ¬¢ ª „ß¶Ç÷¶ª׎½ˆV±Df¿iþy£ªýUu‰Þ>·uÕÑ,Á= ›Þ·ª>ª:w8}/\÷¦ª¾¥ª;ÕªDU©êªú$~ÕÉø…+>SÕ»Tõ5®ßVU'…m«plkU}xx¿°HéuK«êïTõüØÈ³ÀT`ºª^¬ª«Õ¨÷™zçÇ6TÕ{€ð­ƒéªzª.\EÎ9KÎý sî&U³ŠœåUõ™Pöàjº· UªªÇ¨ê»À;øßvZø]W®q9ªº•ª>N÷}ñ*þ¾x³ô3ªê<ª: ¿Hu›f¾¿IªzJ?™ýïÕz1Vø W‡ºŸªRfPFÇ *”ùm¦Ì"™ã …Ïý×Lñ­K>÷qd~UU/ÃÏØ¾‚n§ªêE¡»‹°ofd7ÙPD,lW”žÏ”{2Sîû™ã«dŽŸ#"£DdRæXé¶_•:‘‰%ågˆÈ%Ç®‘Ádì™)·‹ˆYF‡EJ®ùŽˆ|PRæã’ÿ?¯¡û™²óŠÈñU¾ƒÉ"2W9·eÊ .9'"ò·Ìù³+È "‡2/Tú®z³‰È©™ú÷íÁu ‰È#™k¿‘O2ÿ""ÛU¹þè’ïð³’û⌒òóUùþ»¶K{øÙ ÷c×õˆHÿÊ躿gV)3$SÇ­Êü9Sf‰k}î eä­'"Ó2e>-ù~Ÿ‘Q±î£\[hª:X>üë€V(º ~MÉÑÀ½ÀÀÆÌêr¼ª)S‡×_ ‡î ûCñ3®ëÑ=sö=à·u¨þmàX|Kñ—ø1…]ñ-¦®z—þ†7úÇK;çãý‹öÆÎÎTÕê¨÷çøÏþ.0ØØx-œ ü¤9³àœ3`G|‹`oUݾLÑ£Õð¿ÕÎι{ZW¸Xÿöß?;Xßzœ§ªó”^~£ÿ ÿNÁ‰ Çß«{·—\ö!0Ø!sì¶p¬k;¾'À9÷³Þw»¨ê=‘ÓdÞŶ]2ÇþάŸû×Ù BáZü÷ùÞõd0þ¹û1þ7ü&¦¢¹´Ð›õ±L™ëKίRbý?‘ÝËÈù¿L™o”9¿oæü"2 L™á"2%Sní2eö,Ñ癿ÊÛ0Û"*Ûâ‘q™2¯‹ÈeÊÜXRïÝ"²`I™±™ó×Õ¡O¥Vè˜LKašˆ,›9·zæÍzr¬7jF~[h"²MæšÙZ¹áráü¯Êœß)sýÎ=Ôwdo[d䉈œ_ò[;¹TD¯ãú¦¶Ð2çW¨Ö"+){IæÙYæüQYcbÜG­j¡ c#Uu¼ªŽ·Ø]ã¯ã[,Õ8Ø97¡Ìñì˜ÁÈ2ç÷Ìì圛YZÀ9÷àäÌ¡]kè2ØØ9WÖW*L¯w9±¾œ[®œsîN|Ë`1`ƒõN¾ëœ{§äøÓ™ýeè%ι‰x\ðoÕ«Tu`s»ïûð‹ÞÖ™½Â߀óJO:ç£{Òi»2×gW‹Ÿ?®j=#´’w Û™Uð-Á§Uu¯I­"´ˆ»t¯ 3´¥œŸÙß¶Ìùž×CH|xßµ» 8ßø°žsîÍ*×ß䜫´ñë™ýYf,ƒaY)üû„s.;£ZÊÅø°,€-ª”ï'5›N†ìõ;羬X²ƒ³µÖ%ü¾sî£ÒƒáØ´ðoC³sιséöW[ 8ïö,~Å9çr_‘^Uç¾þ}¤Ü‹*Ð5é4¢Ì¹‡2ûÇ©êÑyÎ;çÌ9w&°"¾;×ÅÜø—âͪ:´ìÅíÇæ@×wù¯ e¦Ò½6çÊôˆ\üÐðýñ«s­U˜î±rT[5}tf¿R̨âÜ U} ï8¯ªÎ_©Ff¬¬ËÕ[oÉùQ5ʾ\å\ÌÕã÷ÂK­ì–9~¬sîшõ4Â(ºÃ¨VRÕJ ]w²Aª:_öEäœû—ª^ƒáÎ ƒ?<8Ý97mvqÍ'¸3}WU7Æ¿PºÜ™ÖnQÕõ;À=û 쯪?ªP®«QUî…ÓcZÕB» 6 êœ[Ð9·SƬÍì¿^±T7ÙéóÅ+–ªMÖϦV½±êŒ†sî`ß’Ãñ-ëv!ë¢2/~ø¢Ü6¼Â5]lœNwlë"xÃöbpóÉ­›çœû;¾µvzæðXº‡Ú™ìw½$•Ÿ~eÊ÷š–År:çòð*þ$³?°b©næÊì7Ò­ú´õƪ3aføè’ÃóáÇÕÞo½Fe™šÙÿ_|R-fóÀQ+ªêYøÀððqÆóágǨêŽaŒ«å8ç> ú͉Ÿß‚.ëóÕFdŸÃ€'j”ÿ¤ÆùºÈ«ËÙ*²­£zš´Ù2ÕÆôb֫ΘüœîI{µñÒ©êæy=Ü%d'ƒ;çnªX²œs“=Uõçx7‚®.ÒønßÈÀyt´ÅUuh¹ñÔ6"ñðq£¿O½´C¤@3yœîVÏ Z%œE}þ¶®îÉsι¨÷ÁÌ~­T/YOö¼Tu-º¥ÏÀÛt›mŠoÅäNx˜»Æ׊5Xîœû·sn'àÐÌáMj\ÖŠniW$øÉ«JMý´r8ßV‘uªö¹³-² #×[‘B´`”ºf‹Å—TbÿÌþÕ V}=Ðåtº£ª.P®PŸÙ/b½ ¡ªÃ+ðã?uÎͶÆ;”‚w`þfN*–rZø;øidÙ7döËÍÀe»HeßÈ,C÷ðÅÓaœ3KÖÕcÉÒ‹UuU*¸õº>·sî)ºÃÃ6RÕ–¤>*´A üšîÀTuùÒª:žn?¸†Rׄ›íÌðï@`‚ªÊ– Æì¼;ÀÍ5ÜJZÁø.ðGÀöιÏœs/;‡2ý€+Uu¡\4œ•séîÚ­ªZð§+uëÙ@U—«pÉ™ý›KO:çÞ¢û¥5¦+ζ7¨ê!ªºO¹h†p¾?¾µÜÅŸË{!³¿iæÚ~ªº Þ=êóÞê˜áUº]-Æ–Þ×%ˆŸlé‡w9Y½RÁF¾¿,ECÃ9w¿ªž„XïSÕ?àgíæÖÀ;4v}‡›µQ~…÷G[u¿ª^‰ûY ßY?”}ŸÚŽÅMEU÷§;ÎÞιì‚sî:U= Ÿ³l¼Qûv »¦âœûRU÷nÅ·ÒN /§ë€·ð~‰‹â¿çñx7ž×2"6öQÕ»ƒŒÉøû` ºÂt;?—rÞ!t^|¨Òeøá†÷œs=>XÿÂ8MU¯Ãûj¾Šïb~ïl»b({³:wq5þ>8UU7Ä¿œÇý>Çû9ÞPæÚº ßùøïnàQU½ÿ<½œ³»Ê>«ª¿ÄO` îeïÅßóCñžßÅïU5ÔK®ÁéUÂ&f N¯RîÇ™r;U +9&SnûXD¶¯RÏ,Áéu~†ùEäŽ*ušˆ<+U‚sKBŸæ©RîýPfR…óÕ‚ÓWÉ„<]P¥Žþ"roFÎ 1ÂU‚ì^§‡k×,_+xzDÉugÕ(ÿ¦ˆ¬S¥Þ…Däå2×ÕCý/¬Cw aI U‘sN…릊Ⱥ!ô)”Y\D^+SÏ©Ê "Ók|¶GcÜGý)2Ò ,sl2݃˽Éñ45sýCUÊMÌ”+ë\få~¡ª?ÆàC¾ÀÏ,Þ \䜫æ’ðp¦žºœKsï…Ã:øÐ›QÀBø·Ó«À5Àßj´r.¥{²`F•r'á»·•œ/Æ¿aö®Ç áú/é—š çܪºÝÝ1q¶íºÇÊÝO ­ðð²âCà†â3®¾Ozp§sîµ’KÁ'o-†o=¶¿Vûlι·UuEüøÝ×ñ¿í| «' Ü¿OÖ zÌ¿OžۅιTâœÛ[UoÆ·Gãï…Û€?:ç>Q]÷p¥D‘WáS\A÷¸ii=¯‡ïûgøgiüó^V?çܪz~ {ÝðùŸêiJ¸®ZRɺù´9²•UǨìIEND®B`‚phoronix-test-suite/pts-core/static/images/pts-icon.png0000644000175000017500000002451211150642524023354 0ustar michaelmichael‰PNG  IHDRŒŒ®ÀA> NiCCPPhotoshop ICC profilex–wT×ÇßÌl/´]–"eé½·¤.½H•& ËîKYÖe°7D"ŠˆV$(bÀh(+¢Xì "J F•ÌÆõ÷;'ùýNÞw>ó}÷žwçÞûÎ(!a¬@¶P"Žô÷fÆÅ'0ñ½D€6p¸¹¢Ð(¿h€®@_63u’ñ_ àõ-€Z®[„3™éÿïC‘+K€ÂÑ;?—‹r!ÊYù‘LŸD™ž’)c#c1š ʪ2NûÄæú|bOó²…<ÔG–³ˆ—Í“qÊó¤|”‘”‹òü|”o ¬Ÿ%Í üez6Ÿ“ †"Ó%|n:ÊÖ(SÄÑ‘l”ç@ ¤}Å)_±„_€æ ;G´D,HK—0¹&Lgg3€ŸŸÅ—H,Â9ÜLŽ˜Çdçd‹8Â%|úfYP’Õ–‰ÙÑÆÙÑÑÂÖ-ÿçõ›Ÿ½þd½ýäñ2âÏžAŒž/Ú—Ø/ZN-¬)´6[¾h);h[€êÝ/šþ>ä híûê{²yI—HD.VVùùù–>×RVÐÏë:|öü{øêù ¢‚¡[£°R¡Fá„ ”"MÑF1L1[±Tñ°âeÅ'Jx%C%_%žR¡Ò¥óJ#4„¦GcÓ¸´u´:ÚÚ(G7¢Ò3è%ôïè½ôIe%e{ååååSÊC „aÈdd1ÊÇ·ïT4U¼Tø*›TšTT¦Uç¨zªòU‹U›Uoª¾ScªùªeªmUkS{ ŽQ7UPÏWߣ~A}b}Žëîœâ9ÇæÜÕ€5L5"5–iÐèјÒÔÒô×iîÔ<¯9¡ÅÐòÔÊЪÐ:­5®MÓv×hWhŸÑ~ÊTfz1³˜UÌ.椎†N€ŽTg¿N¯ÎŒ®‘î|ݵºÍºôHz,½T½ ½N½I}mýPýåúúw ˆ,ƒtƒÝÓ†F†±† Û Ÿ©-5j4ºoL5ö0^l\k|ÃgÂ2É4ÙmrÍ6u0M7­1í3ƒÍÍf»ÍúͱæÎæBóZóA Š…—EžE£Å°%Ã2Är­e›ås+}««­VÝV­¬³¬ë¬ïÙ(ÙÙ¬µé°ùÝÖÔ–k[c{ÃŽjçg·Ê®Ýî…½™=ß~ýmšC¨Ã‡N‡ŽNŽbÇ&Çq'}§d§]Nƒ,:+œUʺäŒuöv^å|Òù­‹£‹Äå˜Ëo®®™®‡]ŸÌ5šËŸ[7wÄM×ã¶ßmÈéžì¾Ï}ÈCǃãQëñÈSÏ“çYï9æeâ•áuÄë¹·µ·Ø»Å{šíÂ^Á>ëƒøøûûôú*ùÎ÷­ö}è§ë—æ×è7éïà¿Ìÿl6 8`kÀ` f 7°!p2È)hEPW0%8*¸:øQˆiˆ8¤# ÝzžÁ<á¼¶0¶-ìA¸Qøâð#pá5#m"—GvGÑ¢’¢G½ŽöŽ.‹¾7ßx¾t~gŒ|LbLCÌt¬OlyìPœUÜŠ¸«ñêñ‚øö|BLB}ÂÔßÛŒ&:$%ÞZh´°`áåEꋲJ’Oâ$OÆ&Ç&N~Ï ãÔr¦RSv¥LrÙÜÜgIsKÛ–6žî‘^™>!` ª/22öfLg†e̜͊ÍjÎ&d'gŸ* 3…]9Z99ý"3Q‘hh±Ëâí‹'ÅÁâú\(wan»„ŽþLõH¥ë¥Ãyîy5yoòcò( z–˜.Ù´dl©ßÒo—a–q—u.×Y¾fùð ¯ûWB+SVv®Ò[U¸jtµÿêCkHk2×ü´ÖzmùÚWëb×uj®.Y￾±H®H\4¸ÁuÃÞ˜‚½›ì6íÜô±˜W|¥Äº¤²ä})·ôÊ76ßT}3»9uso™cÙž-¸-Â-·¶zl=T®X¾´|d[è¶Ö fEqÅ«íIÛ/WÚWîÝAÚ!Ý1TRÕ¾Sç–ï«Ó«oÖx×4ïÒØµi×ônÞî=ž{šöjî-ÙûnŸ`ßíýþû[k k+àäx\S×ý-ëÛ†zõú’ú…‡Eêjpjh8¬q¸¬n”6ŽI§¾ökÎ×:úçöŸð8wÝçúÅ7®Þœw³ÿÖü[·‡nón?¹“uçÅݼ»3÷VßÇÞ/~ ð ò¡ÆÃÚŸM~nr:5ì3Üó(êѽîȳ_ry?Zø˜ú¸rL{¬á‰í““ã~ãמ.x:úLôlf¢èWÅ_w=7~þÃož¿õLÆM޾¿˜ý½ô¥Ú˃¯ì_uN…O=|ýzfºøÚ›CoYo»ßž›É_õÁäCÇÇà÷g³ggÿ˜óüLbKGDÿÿÿ ½§“ pHYs  šœtIMEÙ6,­L6Á}IDATxí] |UŹŸì+!@ HHX]@ÁVEpŠ R+Eí«¯VEk«UP´ê÷Zënéiq{V±¯(‚¯bEqD ²†@ ‘„°$$dãýÿ'wÎ{rιçÞ{îM½ß/“Ù¾ùfÎÌÿ~óÍœ9ç£XÄz Öáê¸p Fî‘#G²Qnœô§È*Dx ïªÁUhx‹§ñkàïƒ+•...ŽáNI€c z„`(„í Ë‘§ª-p¥p ¯šáw(E 0H ®t*Üpãá2ábX¬»øPU`ÅCç+`< ¹ ͼ.ß_sEMÃfAïáÍ{å¡/õbµÍ¢®©RwÕ@nÚH½é=R‹äøL‘™”'2óD}8‡Dð¼·àië0‡ƒe `”SÑ káfX5Œ€¨<´F5 ›De=<1’=@Pe&õÕ”—6J䦒YVþ×ÈxÀY`ÅàFº«€P¦ QóáŽ56®¶© X#vÔ¾/*”¦Ö:#K,î§z¤8'¨ sœw-2…{ à)·b 6ÝÀØi”-–‰-ûߊi`GȦ\Aæ©Îix8­™Ð}Hs8!`™…F=¦6–6È–ýËÄú}¯6‡zm1œŸ!@ã ëq±è™ÂµE;ºÚæñv©A$ ¥?ê{îLµÞõ5¯ŠµÕ cSŽÚ) ÓöÙë*3›‡6Îlgi(Í 0 'Ð%p½då4`?¨œÓ(²C,üÖÖ#¢©¡U$$ŋĤ ºßB²o² pBÒ6·Ø–•h^‚lâ§{jþ&£1ßÓ-ÍGġ͢¾®E®oÍ­‚i*¥¤'ˆ´Œ‘Þ-Q¤g%ªY®„‹³&‰1}fiKwEàŸ¡i®V⎃ÆÚ*+Ë†în@öW5Šƒ5M†ûh||œèÞ;YtÏIvUûÐÆ™ÐᅩÓÔçÍûµÏu 3°,ßñKQs˜»×1bÔíoÕ»D#¦+JNL9ÝŠÚ†jq þ;S¶8ŒJï‚4‘Õ3É4?ØÄ1½¯Ã{üP-0h`É@-ÜY+fmÔ,1°°'ÚˆÓNÕ.s  ï?A”ô+úõ.º§c'7¥‡,¦ù»jÖ‹Í«Å7;Þû6úäqºê“Ÿ*è»Eœ¢NÉ»M÷Ð4g© va§€yBn¦ 6°ü*¦YдKöìlœ‚TJKÎ'](¾?øR $jž]¸tÏbùÚ?Šò½ßèlÔ6}¥k6Žžb 8ë#hîhæ9ë0Ð.ܽý‡¶r×]Ø­ý@F£ÒçJgU“¨†VQ)5)SŒ?æj1fÐE‚SO°ôñæWÄ §©å°.¢_±» Öcš8 S”Bç4ú8+é>A'€Y‡ÚVÿ–o‹+ðm‘Ú}MbOyƒhiò®vâãâÅèAÓÄ™Ç]+¨]Ü NOùך­#å Épuz:£ß½Ø%æm?ªñ$@c{;Á0Ð.\zý‰â8½¶uFÔnÈyíßé§$o¬˜<ê—¢wV»ÉUª:¸]<÷î5:h’ÓÄ€¡¦·‚ª—«§ó>£Þ¿€™k'Ì`v p>P³l9°ÜNÖQ™×f§Ô·³Szf(7‰¡ýNëuWîß,þôÎUúôÔ37Eôì›êZ¹iÇ‹s ~¯ÊË·Ó2ñ*§†v¹q ,µ8ƒ²åÀ D‰¯èp-P$5•bÇ·u —ÉmךÔML‚F™5ùå°ƒ•ŠÜî%â‚“îÔëß‹6Õ×R˹3•õëpÌÄçh ¥X’%`Pâ*Yjý¾èÚÅå†[Ù¿j{*²h§œTüCqÓ”%â”!—‹„xw÷Hd=fþñ&‰c ÎÖ³¸2s“ÖV/RÅÝe‘¨&¨aSÀ @˜¸:ÒhËþ蘊갟R¶á ¨Ü~H´´xZÚ)×MzQœ7ú6׌ZÙ·Nýœð+ÁU©±¡›„í"ÛÕSYÿ•QË\eÅo…$ž½ÕhGí‡0t!LØqĹ–”›Þv¼13)Gs]iСCõ¢¬´\ÔÕ¸Èñ,t23º‹áÅcDïžý\©'!™©½ÄØ¡3Ä»_?«‰©Þ}XdtOE¤OYÚ§²o‘Áñ_àÃà‰Xæ ÉÜ{.=RiÏízž2#8ÂAÍÍÍ¢²²RTîØ!RD‘â±%EAAèÓ§€Žªƒ’É©ð£/‰úÆÚín¦âÆ¥TÅpŠWÐÎ2¸ö*oR[È 0ã$cÔU$´ AÂÈ‚ÌSÂyMôkkkÅÆEcc£žLpäææj`IHpg tá.’Ó´ä¾ý«&·#ò»³Ìæ,ÂÙ„ýï!b€GX|¨`€¬lp $÷^êÍoùH !’›~<üÌ„Fi›rlD­B—ô›áJ=^àôÄO Ú·oŸ¾>8qâˆSO=uZzzzßÀ¥E®Ä˜â©bõÆDë‘Ö¶¥¾\À¹Ð„½ [TÀŒHÿ€5ªiØ ?<*™›F'õù¹(îîµþ=ÕÒÛ ÷ÜJ¸ÏðË/…ïˆø'Á¸n!ÊyÕ‡oiªm©1räÈ´+Vü¶wïÞ'û²tÎXÏÌ|10gŒØ¶ç­u›EF–;+6¿ 鳌’&ÌVI:cÅ!j¹ÂË90Ë|ºnÜ«p¥V6üÏÀmx~gfêšõÄOÌê*`‘ý0¾äz‘—¦E¹ííÕ„.m”RzÇY§¹«a$XzÂfQèa„8Ê•´Pƒ8ÜW¸Âì4N¨uù”G}M{öìù¨¬¬l-l%íyšüüüÂþýûŸš–––ïÃD$·WÑã"ñÕÞµÓ|nÍm«a½AÝq‰DšF×0¥K %02çÇ8Ùî–™hÔ_C‘駬Î]è€{ÁKàø)\vCCîO?ýtñ­·Þºü£>ª5‘ò‡W^yå´óÏ?ÿ¦ÔÔÔ~&ùŽ’`g‰Ù§ˆÒƒÿʵ=£„w®©³ŠbO +ÕF™MIj¾«aj—á=¦ª2à µ®þˆpªÚZSSóSLCîLüxðàÁMo½õÖo =~xúé§¿f­-—^zéû'Ÿ|ò«««ÛŒ-5ðݺuý3¿§l¨óQ  „Àµî¹Ýô%›¸4̚Ūúc`Ÿøèé§Ÿž†_zÐÀð¾|þùç‘••uŹ瞻ÜP!w;Ëà¸r Û§ÑÚµkëÏ;ï¼;0]m‘iú¢gj1ŠÅá W«æ»3Vö-1›’ìK„˽…ÞQÂ&%%õÆ é×Ç÷>íï°»vízgÑ¢E‹çÌ™³Á¤7»øÆ€ƒ†<îOÐ K¢ºýöÛg?òÈ#‹°çÓfÁ ØEz‘•D¥Ùv«ÀŽ×ͼˆj˜žØµUˆK_W 6 w±ÚzÑ™äÖ¯¾úê'¬­­­‡KKK—Üxã—Àx½Ó,ÃÛ¾›áŒ`‘U0}£Œ<öØc;7lØð²ŒâC3zØãDÓaÞ÷ro&°k‡ÀØí\yËOÑ¢Mp¦ËA³Öbóò_|Á2–ÔÒÒR»~ýúE0T§ÝÏAV˜9pe÷\)\=œ?òÍŒ3555íóWȘŸœìÝ-hnb3"Cä{¹Êx8N+ àòœÊ9|øðΛo¾™F°)!ÏÇüÇÑ£G_0bĈ§Þ|óMuP›P¨îS¸ppÐ^0kËmÚ3Û·oxzÆ”ê¹Ï‡‡ã„8rÄ­q²¿ŒˆÚ0öM , €ÀM¬d7V5¿Ý¹sçacÙC‡•(Å/ÙîÝ» •¨A¨QÚÝ”S™†wo0y—/_þNIIÉÅËél¤–æV<üæà÷/ 釿† fU @É„›‡|œAw©ÿ|ÿý÷û»¸¯ôõ믿>«é¸¯ô¿°P°>Ú(n€b]ktýõׯŴ¤Çeº?_½AÚ¡YɆ‘jÎ_Ó#“ pãáà¨]‚¥ò5kÖÜŒÂÃ)öIÝ“O>ùsš‰@n¾•Á0És#‰Ó\6°›°7Ô+¡>Úy/ŽWxÉ`Â[y Ò–«ÀO›Ãkí"ÀË{͸qãö#Ê}’t.oáŒ`áò—KcÍ΀.b4ÀTUUm ôžV|¼w‚à³R‘ o¦µI ã–oZ‰ßD€e2˜hÔ† –¿àW¹ÔSá6ø0•hWpªÚ n°°^½~,ÙÞÄÃR"ÚÆ¦ L7Tmñ£a¤Š3 6ØÏ¿ ËQÓ¸`kSʽ°µ£ªÈètAl*¢Mm}—Àß~`ýk~Aö2:­†XÒpAÜgqJ4d·ÊP€ZåCZ—r:jLÛ¥$àeD‘ N \<µK@ÛdÜ@h‘›á8*ÝŠtn¶uFÒí²^½zñâ˜xx]Ú0‰ÉÆÈàEø™’Øþµ¤}WÍjŸä“ÂU΃p<eugòþìSªsEtÀ`Iæ}Ú!;¼™q² pÅT_ã—3u²¨oÒçý 0p·"nº]c•ÉôE¦Œ†·ùŠaKZÉ®˜›yú6A^^^Ï@ë€Áø$&BÃDhœìȸË;ÓBÜ\¤Ï÷Yt.ø¶ÉˆôøÜÏà8`õH» Yˆp¤IžQL~ •××{•jrJä,‹ÈÕä°7 ]¨_/2aŸðý%vZE[Àã2"}ƒvÂûpœî䯛iÏ!/à›(*qÿG£œœœbvâã&©Î–’¹ß}§ zÓ‘ñ˜Â*…ÓâfØO,€õäYMu¬Èœ´Ã O†dÊÎÎ&ÃNüº:ïFt ^4)ꌀ™b¸xj”ë ivQj¡o Ð ”ËiÈŠŠÀC›&RDí¢O¸å–[à¨B/§s9ó:{<žÐVIN ‡È×3ÑpM<,NC×÷s Æ;,ÒÕdÞ†ˆõ]pÁcd؉§t¶´ŒÈMG¬´Sö í ã¯üQ½w‚ @sð8§:ÐÒÖŸ0?ù½eþ°aÃN“a'þÞÓ©Ñ tÖqpê„Ì]Ú÷œt¢ž³ýäËlïÒC¦„ÇÏ‚Xm…4mÚ´^0x¿H58;£³Gµ†A/µË2 ãUï0‡Ñ EjGX?†§&ãkz<]Y)WHüðÃêr·›Ì Ð'XÃi×ǩ讻îší ÁèH\yyù»¯½öZ5™ù\u÷îêoË‘W˜:`Œ=à`ØSÅRxÜ ãÔÃ)ê^¸cΕ´+†Ài4oÞ¼Áx–ú.Á'Èt°`‰ï½÷æÂgZ@„É)“««€ÊºÉœè¦°eI›!D1ÖÅ®º.3á ¢õÞó’g®Äc)&|N“8}õÓWD ÞÔpO¿~ýÎr*Dòáõg MÿöÄðÕ°Eö€‘Kj·Zg¿l3Úaç²Á×ê¢Í²xñâùPùŽwm9õÐa­«Ìâ#DxSç²eËæâÌËD-!ÀÏ>ûì3J‘JØýƒSöcdD3²xÆ)È8Eùô“KnèQhôá‡þ{#eÜÄçÎé‹öAFŸ 1‚Im´páÂïMŸ>ý6€°ŸL ÄÇ –Ï;w“§ óJµ¼ŸñUY…ýɳ×0ŽªpÉ7–²vãžH¡dX¦ž/ã&>yµû?&y>IÔT4˜Ç?9˜)H Ã1†z¼`ñq‡_GÐtÙf÷õbûþ]k\Cï]V¡\ɨԟw¯±š0¦«<Á†iŒêFî‚ ÆàE…7úf –n¸!„ Å$|Ÿ`tÆ}ž§ÔÏ>ûìO/¾ø"—ý$€ñÑ.LÜVíÞøPžŸ1²Ÿ’¼ûÎ^0j.{¹C¢šç‘„2â"q )‘ò8ØW^y%]qº±%.‰Á?øøã/6Šé«Æl1À‘f[0ˆLlÐm8ûì³_VŠ–*a%èoQX]ÚjÊls´[#”ë:a·éN[A«dΟ?ÿ|½„{0íoŸ7D ¥ÖÀ¾G±/enW‰I§¢{ï½÷7rW,<1UcÂéññ£aˆõo³’æ}œ£UÀLG|N Uøá-@>§#n­Çÿýï¿/I¶´•† ò#?òÂ’û‹>ôÐCì olÓBfÿÜÊ÷3F~Õ°YØf¼ÙX„iê"—êãj¨¿”…×’][ãTï,þÖ­[_›ìAGò2ÕËBã¯Ñ#ž€ °»½l3¶ }|’̦¥öœ6)Pózî™gžù}8úžÐÁî³¼ûî»ccŽG.$5#ð-œ·áž€e‚ áŠ=Iâõo¯w}lR}·£ö˺T¿Ói š÷JžULû,z±uëÖ­Ç£V6Ή@EEÅ{3gΜn Üvš…SÜãÈ{Î – ³DEí7®7WÕ.ÞN»°B[Àp2uÛ±Rô(xLî ¬ÆÂï Á^ÑÂß}÷ÝK.¹ä:®Dœ–w›ŸôÃ1…ë`KÍVÝp´^5›w Ü:O:TI54ï/|3S|Yù’ëãÂqÎËà"S'SÀø™’X˜¢"K\>£ÃnE­Ï„RsQQ‘ÀŒ&‚—ÀJdŽ^> í3,¹NËR«mÙ²e%n/”óÍ7FÜìÙ³Odyºñ²Ë.ëƒûS¼wVG ©ǔÖÃÀ}kËíb_ÃÓ|7 ³}ö1W™Ét³b®¤½ P¸"ÈJŸÛÁ—HxºþžÕ«WßC>Ï2k§î­ÊÙ¥óÍOø.€ÆÂ—úðÕ§tòiD,áµ7+xVgE`,(¤jTWßä-óTŸ…@Y]þ4¦ *¡ðR‘/`VšÕÖ‘€1këiX ìêj@áÀòUÍСCóì«~ÏQ„úÆ'»2Vy¸Á©ÅåñJ†­¨¢vØ p¬¯^*J÷} šm„X‰ 8ö‹²¤þ?²*3!Ö-׸¥cV4˜´ðj«© !`$hpsQhOZăcú>Ž‹m2?³Gã»6q£è–•‰G¶‰µÛô2QÓP&ö.Ó¢gF8pB®ÏQç÷¬ª÷«bÁ¥?·ö‚à zJe$刴¤lQuˆ÷ã§Æú#¢zG‹h唸e²¸vÒ"1ªðܶÃÿ··Þ)¾Úþ¶Ojz,>1NKK‚MÇ÷ãâaó“OEâa$´ÛúÒØ:Ý¿ò|öJZ50¢€±j„Óôº¦*A,%§Å‰^ bïNh˜!Í­â©·¯ÿyÖ1¦xª­Ø^ð¦„Ì6 Ø2vÁÌQ¹?2NGŸY]†í²ÚýEµœâ:ÎOÆ-Ë^ñxÍ»ä@sX<³â*ñÁ†Å&}ÔqíŒdßO,¼M½vniX’½†‘ýeY¼kf$¥Ä‰žýãÅÞòVÑŒ/²¶iÿýÏŸkgüˆŸx/J½~5ìåèò¡Qy?Ù©äu성»@FÌ|?ƬÈÑ‘Fƒ á4%iÑÊÅ?×…´õ#Eu Ÿ·Î-ùÚÖ{ÔˆY8jÃÎ hz%ˆät/h¿‹Xö¥­V6ëÇ.™vѰ'¶‹­váEÚOIút—ìÇî]/ª¶·ŠÃuœwðQÉÕsE}£ñÎD[žc¡œ‘SÑðœ)j+g««°ÀX;úÒsÆ‹ê²VÑPÛŒ|þ HN䡾6RµLëª>oLö”Úü;a»¨wÎÕ<ŸpTOI>=H¯ñ"-Ë;=56×k,œº”ïq‹u©8wt/?öµÍŸ,óÔ»p 0†Þé™/r0EioÈ£ŸÝ× "{—ŠR³üǨ¥ªÝR ¸0‹ˆMI&½•#¸Ï 8íìX¼̤E¡'Ñf1LCÚÁqãøÜð„ÂÛÅ´á>Ÿp¼ tåÕŽct­,_‰¯¥ñ­Ð?•5mÛ÷¾X½ãq|Óç_¶}âCäÙx œïT;¡ïLãÃä|Åç)3æe=мç…ýÍGY÷wÍËZf…ˆ˜u(ïóŽò®Ù±V³,§$µ{0àˆ_ wß´×Ί¶#£Ž«-¾³„oˆQ¬b=ëXÄz Ö±p³þ¯`´(CßIEND®B`‚phoronix-test-suite/pts-core/static/images/pts-308x160.png0000644000175000017500000001122611155254055023356 0ustar michaelmichael‰PNG  IHDR4 µß`LsRGB®ÎéÙPLTE         !!# "$!#$"$%#%'$&(%'(&()')+(*,)+-*,-+-.,./-/1.02/1302313424635746857968979:8:;9;=:<>;=?<>@=?@>@A?AB@ACACEBDFCEGDFHEGIFHIGIJHJKIJLJLNKMOLNPMOQNPROQSPRTQSTRTUSUVTVWUVXUWYVY[XZ\Y[]Z\^[]_\^`]_a^`b_ac`bdacebdecefdfgeghfhighjgikhjlikmjlnkmolnpmoqnqsprtqsurtvsuwtvxuwyvxzwy{xz|y{}z|~{}|~€}~€‚ƒ€‚„ƒ…‚„†ƒ…‡„†ˆ…‡‰†ˆŠ‡‰‹ˆŠŒ‰‹ŠŒŽ‹ŒŽ‘Ž’‘“’”‘“•’”–“•—”–˜•—™–˜š—š›˜›™œž›Ÿœž Ÿ¡ž ¢Ÿ¡£ ¢¤¡£¥¢¤¦£¥§¤¦¨¥§©¦¨ª§©«¨ª¬©«­ª¬®«­¯¬®°­°²®±³¯²´±³µ²´¶³µ·´¶¸µ·¹¶¸º·¹»¸º¼¹»½º¼¾»½¿¼¾Á½À¾ÁÿÂÄÁÃÅÂÄÆÃÅÇÄÆÈÅÇÉÆÈÊÇÉËÈÊÌÉËÎÊÍÏËÎÐÌÏÑÎÐÒÏÑÓÐÒÔÑÓÕÒÔÖÓÕ×ÔÖØÕØÚÖÙÛ×ÚÜÙÛÝÚÜÞÛÝßÜÞàÝßáÞàâßáäàãåáäæãåçäæèåçéæèêçéëèêìéëîêíïëîðíïñîðòïñóðòôñóõòô÷óöøô÷ùöøú÷ùûøúüùûýúüÿûþÿüÒÎÑibKGDˆH pHYsÆ îétIMEÙ 79«3f6IDATxÚíùsÅÀýVmMm±€  \ ˜ÁÂ)rHJ˜„ 9"HS|€ˆ°H€‡€*%$ äÁpÉV)PlI*©J8r,¹vSó¼9z6»Ó=;;»3;“÷æûK6stç3=Ýßþv÷·_ 5•X›H–Óÿò‚¶É¿"I7¡™ÐLh&4š Í„fB3¡™Ð‚ˆÛ%–JšœÜüH,9&4š Í„fB3¡™ÐLh&4š Í„fB3¡™ÐLh&4š Í„fB3¡™ÐLh&4š Í„fB#ˆ»¢¼¶YghÕ7df¬[†dEZÍoß.NênåšêüÆÜm'Kõ€æ9·¬„-oDZÓ¥µCH*ô^˜_]h®U ‰4çŠÒZP³®DÚÃY¡Dš'wœ"±;ÝQæ^mÖ­nw·PTi÷åí¡Ýè Ð  y÷vUê‹:¡}kÖíÏJÔé–¯)´µ­šû#¥ %•im9´hw_U®QûÓZAË€Öí;*,>õhí´hÞùá*5¶Vh¥íZ´†Éák5 B}hãÀøÐjFG¢VŒKmhÇÁøÐFE¦W×Ru¡5¾b|hÞÉ‘*W©*´l0>´ôÈ5X«"´æƇ¶[ Õ&©í’T&* £´ÛA{xÖ¡iŽoädf¤z1(µ2ÐÚ'È rÏ!¥ßkË­*ø»kb¥A¼æ¸îoº:w޾Öògph¡ˆ—ÿ: 6š%Óc¤1‚Ù’Òo|‚k%­ÎîÏU‚æ$xT.j`劲åå~ÁL)çÑ• íÁOü`¨Ñ¨&‰‹±÷¤ï¬Z,Áù¾:ЖaÇ'h>„çÌË#ih[É¿K¦yëH&­´ìøuÍ¡í$–|IhϬ$Ý_úS.ç²DâC_R–vÚPÐÖGM\òY׎–)j@‹N1´ª6$f¡ä]ŸDzê›j@Ã:žó méÛt…–ùó77¿§´îâÃ3­¹ ¡ ¹Ò}ÖðØå*@{-X£;4Rïk£’„þ×6  ÇLÛzA›‹«=JIþñû_UÚtìø1ã@kÀ›Ë?Jò¯'¸p®G ïì×lh„¯s©2Žá)¬ŽÚüÄ—†öÞ/.W¦€·>Ê9´™F†Û ‹•j…?Þ㈡Ñ$Çí§†€æÆ¿¿”jà¶JUÚ´“åU]Ÿ’€ÚÒOÜzT"/• ZB»ŽéÕWù{ûKdeäîîÛ‘yÞ©þÓ¶Þðh-ËísåÐpwÜDF£@Äb[ìÔÞY?§Z#6¤— Ð~VeêÍŸ›U‡†Û5aÔ«x¿½I…öDuFïìçÕ†6TœÅËá4F+1M]*@»©Ö ç¤Ju¡aŽî1á@ÛéyG 0‹Ô¢öÒU¡an«9á@»ˆ©yU hÏû¨E ö© ͱiKþΪvRªQÛ¨"4Én£"y€%sœ;Ž ½ÌW˜ðOêÍæØª!´/ÂvKæ¹+4KiÊ™êQË1´" k¯¿øðTÅIg©ºk,hç±dþ »_“”§}ÒªµÞ †‚¶K†ï¾`“f{„‘¸k ZÔ6 ÚR,™îxv¼1ŒÔ=ÛTjD©R#AÃ)¾Ã·KþFXî¯âYêP[j h XIèÇŸÀçgoÓkøÏÂjµ'Æö;H´’w°ãÃv¶z.¯ñgºM94wXÔ¶Keòéâ#]O"rS—žúá@¶¼ìø÷Hâ|ØXåÐbUV×FÒ)7;“EGI*–¨]5 ´ïñò$L"]µ]4äwB5¸Î(аi0Z8uWûdô¨ÝÆëÀ¡v³Y8W…×,ñÞèQÛ‡^C@óôÅ¡µÌÕˆŸÜ=hž8 —²ÞÐváX†´œÍÃ϶­ˆµ¯$š(¡= ØN{ýZVBw;9zЮIÌ«×Zc$´û»¢­Xâ…ê 퓃û'ù5jÆ–õ7úC#N¸¸pÉû„+¬7¢íž„ÿVOhDfÚÄžó/ц1äë ­aŸÏËtò8Gs4 -Àò-Òš+H#U|]Ù_ýV™öÌ*ñ¬Ÿé ­y™UŠ%ÇUlÛ›´††7ÝôìF’ñXùÛåñR#=š2#ŒÿMÓ š÷œd>¤Ò#½Ö»g†K3dM¤fj¯>ÐjÎ/“ÏH‘'Ñ}Ä™šøÙéR úðsbH¹•hmÚ)IÉÏݳfj¿ îäl‰G‰ùa‰I•,H`³êLGFô&g4NÏmDò¾Ô{¯ŠQ<»ÉUÌ7´AÒ5]Œ-Ök8h½ƒíûë´Ú~ÚhÐ:= n¤PºCëã1´.Ë´gØô†v™6´¸Y+ÀÙY_hé´Á  eØÕ[Oh¯× Úœº,ÎÚéúA X–ohTè1g²) YïІ‚ÖÇ© {ó÷0] µ½F µE™‡§9»mô¡uEMÒZJ±r×à|K”¡¥ˆ×ê müµðFÖÒ-Q„fÛ‹) #´”›a{nJVvŠ´Ù„}½ õÛ™“ß{a–U{h–÷I™ëJʸ«Æü”¢íÛhJÊ’°¹£ ­çÛ‹3 iõ¤üjΚ¹©É#ˆ¢"¹•† –4åÓ¬ëÒͺÊÐæ;%å^qåó¨ŒVj/úÏ„l…Rõ—XXƒ§Q,^ífwÿŸ‰ Í„fB3¡™ÐLh&4š Í„fB3¡ÉB{˜°Å„%­Œ[ž›óã4àX¤vÖ¿fgŸ<Š­ >®K#=¡SÌð™{¤æM\ÊÎv«íB‹ûì¨VÐ’ž½S­xù 'H\0 Thm^ïÁ ìfémïPìð ÿ+5¬|2™gY÷㱭âmÍ(xÀêÖÚÅÜÜæv°ª/¸TN²Rt¨Æ ~nŽë°Ä]Wss¹×W>iðÚÈ¡Ñt ÅM¹ÔZ¨¢š ›u -ĻL=‚‹?"@+  kt•`…åÉ}a`¤æ>3ÒíjŠÚcW€ÓÝã*óHCûÛ6-ThžÒŠ0¡Íà–SpÐj×¶è|H¸µ.“ ô5:ýÂn?Iç÷à²z´‚ 8GÍÂ3/°Ûké #,S‘*óìvvîSžÝžŒÆiîõµ# ͽ¡SeŒöM9É­ìèÂÞXmhc·Ûýç0¾•jGêìv~ ’•v;£S¥=ÀÆÜ½ž;x¦ SZM8Ðús!¥Yh.{ÀôrvÉ ×R¤òõù€ƒ[ØÿY(mè¬]>  ÅVïÕФ!=‰Ðû¹´Ê|ÂÔüÿl4#v´~óû©ð þ¥­œ¹xžÿ÷0,?ÀÛ~ A¹oh‰=ö»•×ÿU—rhl,èRÚÔX¹íübæUr6Mó`€±yê®ôX @› 69ÈœÈä÷e1]ÉN¬:/@[ Óós» ñ†hU=Q0Ä ä­¡¡½ ÔÁúækq`«æ¬næœ~^+‡] é)Èc8ŒÎÎç+’‡ÖT ðs÷CæP… ì7›ëöS¤M„d U&ðÛO²ÓY¸Ih‰{&pïïóI\CÐ|ó!“„½ÂØ MŒb븓MŽÛXrÁ8×ÈÖiù¨¤;QdÌC¹Ášæö•ŸU&- N› ®ˆeÜV-µÚuù?ÌGÖµA㿳u\%/„²eaÍC;?õéãõ}–gÐß>n¤j?‘– __ýe¡%•ÿÔƒýó]`5O„FÇNh³_´j ZGRAŠ,*Û#xË…^,Ú‰nÀ!^»x”D@;m7:´ ÀÑR4æ!h¨înÃ?®¿q;›Ñv)XîʶžO|Á‹§Eóå–ÚÜ$.y‡[âãÚ!a­;m)„Ö1팸ï™ÍC;'|dŒtx‚t$¿UŠ#´jþH[Z·àj³¼ÉQļ ¾wÀ4ä\±Ne›Î͵Á¡1ú²û—w‡ ©{òùŒPm‚ÓÕÒ‹Å å,Nã ‘´”–)ûLùî) ¾Êd<Ø#- p<7¹Ñ³‚m;_Ì”Fׯ`.ËšÿG±ÊM hL3õ‘p2àmZK‰bà…ÖÌF™© ©¤M¹ z§®”ÏÊp‰¤»ˆ©Ÿ”´¯…l UƒVز nχã÷ƒ¶²%LZ!ÚZ,(4ƼcÌÞw塹‰¡þž¦ á‚Ac3wˆÐò‚vÝÂ…VCÁËès*CeÉÚ1€…– m¥ Úu€å ¥âE´ž1œÿ“]h$W°-ó˜YÇA^óÃhèóù'è&áB£§øvÃ] °^­Î ÚÏ'™&A =ë‰Mô#Ƽ)”…Ƙ‡×<@½ò ¿€Ð™çü1(²Õ]J ­¸¥´Ç#e¨­H˜f~Ù ¶ 4¶N˜T‡~$Ó2Ð&ƒ•}ŠSL3X)Íû:ÀTµ³åå·ÜïUÈz¤­Ð®VT÷ñùz& ˜çéœ9áÍocCóZ #Zysß6D­V=hlðÛê‡1×÷´ZCæµn;³{c"Ë@c>ࣷ¼rݨ"ÆPMÎþ%w Ëâqü‡T ´}&<¯gý É\ fä\º–Ãt¢Gq©ÿÆšlÓÚåœ= nÓÙÛ¨šµ.8|&oÓ*Bóm J§1hô“±Âjš“¶;õ¼é ÙÄËQä[”ÆB‚evùõ繸ôK  2½Ò׌²«S¯b ]Ö•=ó÷{·0‹zm¡X¸ @.‡ã'ÿË*޳ÈXu8¯LñæIƒ†MÉ,…;-g¸fó“qñcæü"£ 7¾ÝÁwÈ;îÄfa1Z¹Ãñ^Í_t8nùÿßt,íÍø±³³r½«¦ ³*Ïw›{ãÄÄ÷Où{9Ž,xÍ퇧øú qüŽjºÉá8Â÷Zäª]Ÿœ8YK™“'NX’ÿÓè¿„ðÌØhˆËIEND®B`‚phoronix-test-suite/pts-core/static/images/phoronix-test-suite.png0000644000175000017500000001305011154643417025573 0ustar michaelmichael‰PNG  IHDR00Wù‡ OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛbKGDÿÿÿ ½§“ pHYs  šœtIMEÙ‡ßè° ZIDAThÞÕZ{pTÕÿ}çÞ}f7ÏÍ;!"] @Ä'>©¦¦b­:4¶ƒj§ÖÚâÈh§µŽSµVg¬Ô¾iaªPì8 ©¨`­¥‘ðH" $Ä$&nB²ÉfwïùúÇÞ w!PãÎÌ7wϽ'çü¾çùÎw\ä2½”RBaüÖs‰Ä"—¨0+¢—EôÑbÃøS-¯ VÅÝoWrz´8  …YîBéf;‰ÆÌϸgTësø†_S{ÇöãtäDü$À<"$âÂʳÍ@±s!¦»¯Õóm—ÄâŒð!Äûf¡NÊ3ß©ËÈoº‚ïåø úB@%ˆTR>^f€(N©ï%ë`Ö¡s.K1Ïʽf¸¯G®mÆk`÷@øÃ C–d1A¾½û,äX«àPòÓ´¥ƒƒèêì†ÓžƒÚšE(ÏŸƒÉB"Œ†ðô¶[PåuÁêi>äPòð¥éÚÔl3CÛÕ°}<Ö‹ÈJ í×Ïp_KW­Ñj~À€49FpKË¡œî“¡Âkß}ÇSàJÀg‹Ì —½W̼­ý¯¢´*' ˆêAŠžÊ’R^JDTã[uè¨ NŸ_Âõ¥Ò4÷¢×<`?R? À“ Ìú|¾ß%À'†$À ìïíímõx²jÕªçÞyóæ=^ZZzÿ»ï¾ûŒY+Ì §Ý…*÷R0S@ ¢@¨É i{›d‰bç<Øc8{š-3óí\FŸÊÊÊV*Š²ßˆn‘“'OîØºuëëëÖ­Û PSS3èóù`³ÙD}}ý‹}}}W-1Ïï¶#ÈfJÙô( ã9ÆJ©I™ ™y€WŒA €:ôS)å ÏçÛZYYy£×ëýñºuë6þ2èóù‘HDyâ‰'~™¶¢ªBÆ29|r?ƒRyiŽf€¿ À«FŸ¾`ßÃ?üR__ß®P(ä0 0¡hexïÞ½§c±Øˆªªî3~—~ªÄ™ÔWÓ¹£ P’䥔N3©œLÌ}¡££c@¢(R×õ³êV×õh8–š¦Ì HfàÉØ£ (cη…™™w3s=€Akˆh0a2ðgdBD)›I,ƒPœO&Jg°9SÚ,¥,°@'37hBƹ]“cÚÔöE;3ïdpÏݳwÜuèmYYYÂb±ä˜M4¦k PzXçóubN[ð:"ú¡âÅŒOM6Õaæ—AXJ ;7¶5,™<_b×’%K Eqó³”1=ÂîyŒóBIm!‰è“O€ˆ|Û |`¤KÌÙg›Èår€kÍš5_1ËÈï÷³Í®žS/2rg¦di€ÏØbJÌ'¥i‰E ˆÅ4>À¢(JFAŽŽÚ/^<³ººz…ù}[[ÛîœÜœIñdˆ‘P2eö›7Dkò6X3Æ=½jþëCË–-»N×õ²Ô…³³³U³6oÞü17@0l?qâÄ1Ç÷=>;âÜŽÈ`3ŸN±±­!1¶HµˆË›¼ÍÏ®]»öÆM›6ýÀÞæPgó¶oßÞXQQqS3sKK˯׫[-Ös²çñ(¤K áh1¡¥$OQÄôpR„#¢¢Ô‰š¼Íøsë-hò6h/((¨{ì±ÇžôûýGX Í©sçÎ-_½zu]cccCUUUƒ)òP,illÜÜÝݽüäè[k#ŒD"&£é „µº‡Áªd%ýALFPÝ—0!&¢7x>•‰»gïHÌYåóù^p8•v»ý£m۶ݵpáÂkŠŠŠ®°X,©¦—ðÖõë×ßï÷³X,7ŒE‡Ð3|$í¬!YG°p0ÓNÌ`–R¦¥‰}ÀHŽøº”²ZqÂ?“ˆªÃá°Ûáp´¶¶¶þ(77w3saaá¢ÆÆÆE©Ç ÓüLDtðàÁ?>ðÀ{œ&"b–ˆSjŒá¤}IMûHœÂ€÷#:ÈÌ+‰h3÷¨ ˜ÙrôèѶ 6üÊëõ~5ìlµ¨Ä˜ÎÎÎæºººõFa îü$Ôƒ2à¡øz’s–FgÜÁx¾JD:€|£Rç`D"J দ¦ÇÍfa·©MÓ´¾={ö<5}úôÕ3s 3¿ØlŸÿŸîßóx`"!Û^fnɨÔÅ2Îðyf^c}¼f‰Úl6zvîܹcùòå+Çë6D ÍAÓ4D£QD"îééi=y¢ãÃòŠŠR©ó¯I`.€‚v½½§óçÐôDZèW;çØÊˆˆš3d£é&DLŽtsW`_£.µÆ8^ X Éã gOSK¬¡•oí{™_Ú@Y¶Û¡ËªÎf§œf;+yil)IIYJ¨x䎳šæ»ÍþÙ_ñk]ýþ‚/| í™}Ìòõ-;þÿS’—Pf¯LUŒ•%¹L!ÖÒ°‚TGT—ÛSÀü”|>ÿ§ êàôÞFÙìz†TÚfVƒ™étÈê‘6ÞfŠªet4”÷(±Íy¹d}Ô8—UèÚÉãA|Ý9º³ì›ªEŒýÓµœ˜_ªÓXC— ™[`E¬R;½y‚HZ9ôóšSéßÏ IM"Ý·vm(¹ßÞµVñµªØ“#©HRT•pã6}i`8ÒÁJÒT• rn’Gl®©[$¶·Gn@L¬:§)—­¿â±I¬0ç2 õòÖ•6ó|ò|§ÛçÞç@—™s÷Ö¹ÿfþ}zs¾Šb;n_Š '÷Ti12çï­sþÍüúõj{Dñuî[h{_°¶¿lí"Æ«Óì+ZRubb”ÜvÃiqiAí r@ôÐ4F-ïËwÝ—ò%Ç׳ÿÇS«b^ L»¼ž•›•ß]ã‡mûN·‡i3…¿)Ù Ê”)¥øêsÏû^z›IÓ·íÓÖ‹Äñ„zkß¶Ñ·Ë.KÊÐ\nDå3G·RB’Ô•·ïÈ‚ a²žÐ}÷¡Ùª‘¹ü^]d«õgj4«ÓÑqd¢2Äem6 ø!n¹Àøz¬ŸœVÌÉ—¾[ÈÔ*3&VîKž²§‘!Òä‰ó¤»Ê”¥(ò¥­Å’I>¥Z`| à’ÃîâúLÍÊïëMá"nÖ!ÙÔ¨À†ò‡*aµ¾[Áöù‡³»Ž{Ïò¶:Ò}جÿìþêhù[i>ìVöõ5dŸ"Gd¿Ë*ÒÓÈÑò$vKü°r§ý-7üÛgŠ‹¬.KÜ]ƒŽn¼·i»K¸/ZU6¤ÓV$$)qߘÓN žRJT@#Ôi“·›ü²¿âÖ»ú=ýUö'ðil×å;k*Òwg“eK¶nuh±¤Å§Þr3èy(Wk ö’€¼ZóöWüZ×G¿ ]]3 “þ†R?áqÿ6,ö®«;u±Ø¦Ìï¦öý›î[Ž5ÇI¢ÓݘÍ>ÜrCA/ÅmæøZOÜZyù¦‚eh×Ù'P¹õ´kW¾ÜªÕYp($A¨ª«J\U%å6!GÞ§ã®Ù Eíúî»» êe=ÆÜ3×!ë¾ú©T#•«Ÿ**¤,Fe'ø­°m?î iŸ|.±6‰ÓÓ̰,ß2Ânç¸ë m%Ó Â£NŠ•üCHŒPïoþ$‡OÛ)9%D©G’~$éß:N¥(ée¶¤¡ ÚÎ<öÍ&‚@hÑ£@¯þ0YcÞ­­º¬]AL¥fªt×ë°b6”6+°–È• %<ùíÉŽâ½=çCË$•o ÍÆ×­ÍÛe}ªJ¨,Ñî« »Ž; W)Dê|¶˜÷ÚRÙœ²¢>!„óõ£[wç?ÚU¬‰‚öÇHžÓÕš2±qWBÁTv¦.4x€ñê’¯d”H}X|ˆ-É.ÛòRgùšœûðüä½™ôµÜ–Ä®¬×D»êÙ’“;ö¡L§¹˜r•M,GTyô¶¢Gœÿë«OÑ AÚ½"ùÄM ¹O›B¹mzÊØ—Ce¹ùÑ)R“ê•¡ÄAøêý°/ÂÇ…‹©4ÝÉì¾»2ï‹ ¶«KJàŽ˜SÞHáO¡§•1Ü}|¾VIDjRõ§ðÊàþ¦WŒ½É`{Ö.6ËRÛH¬K~¤ÜjJBR¹m·ï²øHÚ î…¶³Â“R÷ƒß¬¨ä \,cXe !i÷ºÛ€ˆ°ÚÇ?TõùnûOþD¹úö¿Lxݶ§’™;)ÈÈl«ßSu¨ P8CŸé¯Ÿ’ÖKýŠÇÿ—lþ¦½s|"½eâÄrKöÄ’´ ©,3~G pÿ„§“÷ÈAz];üF}4ºŒÝ°±U‡Õ,›ê¢°Ý:ÎÈ0Û„ýAÃþ¤WÛqÈײַ­l8WÚGljM¼ßà}•ÿµßÑïé ³¶ÎIÍUŒ!lz¡zÚ³’ÝJ•0„½ÞÔ¸ÚÒ´•%IR‡¢•%IRTALãÑÇ©UçÔo¡vN•™«ë©ä,mfW­«¦¥!|½Ti4§‡9Ïn2¿-j>«r3«?] ®dºûý’ë›ðVÜýXÝdºûý’ë›ðVÜýA`~¿àÕ•bÿsN­TeÐ×~XŸ§gOÌ™žs%±qU©2²Í:Ü[f3È;NqĨ¥÷šO` ¨ÝÏ$z^$¯Ê¯Ø/ÜG0RÒ¿ýé¿úhuW陎úqmÿß»ÿôjí Z”úÕ§‘)ÌIƒ-š¨I<)îzÿõ×`ÛL® ›¶¯G mïg×õÄd,$T·^®~Ù„Gd}õ¸‘ ÔwaºlÙ½ÝÄÜÛšÏ×*«eÛQö‰®¶‚–™H FažÆZm(m´rxJ$žIhÿ /K˃§vÃÕ|æeê^KË’X­\´ùmö?K€ÚVš|ñJÒÛŽ¼´ž…ÊR9o\C¢w…RÊÙÝßIÝ>ÿ*´{× ÒÝje³fÓ;ž¤[òRBÓ!ç¶ÉAã´v†ZRJ‡š{‹–Ð-‹ó¥mÏŠ·ßRüMlÈ“gߢ<,†¨Í÷"[m´²Ì…õIi §»Ží/¸…<€a_E^µÙ§£þcŸR¤Ð•vc{­m&õ²]–Z.)ˆ›g̤$”ú‚‡{Á[n•1^8Î浈²õ—O¸­›ŠžäÝ«;[ ) IþG €tºÝS|™ÿ\õ<¯Ó2r/«JL…<ŒuW¨·³HAõ-°ûêKSšO¯ëCÀv§µår²µ·Ï—FýÀÚq®÷yL³':ÚLºÿ ê\¨k#žÅ-i,8GÛSN¸Ÿ¿©O¶íßí{xVýFëÚæw¶¯Êm"bbTæÛ54Jn3ê@Xme?Z¢’1ÒRå ‚ï Õ¤Q2ÎÏrm½"+ ­9¤só¥e®Õ¤üB’H#Ô¦ðXÙw—´LÇñ´êt—^ÈñVËU80§ì Ž@XŽ}9 8Ü_Q‰m÷w;ºû"ůͥ¢¥‘rWŒû±ã!ô¥G’‚¶]H?;jkZÓÀé üâØŸòµñÕ xË1žH¼º¡ÙKCÖ걑‚)m.M6’óí¥b³Z%%HI\(><óê¥?hlå÷»?'dþ¦Ê¾žHoçÄÿ•¬޽SzåôɯõÅŠCH*RY¹›qd™(åJ?xt›_´6rûŒÝŸ“²S_¶px’òcÇÂwsŽ,ð„"Û”JÌo×A-¼C›þÂGz“Ö³–ÝuëB•nÀ·éU·â.:ë^Ì]ZæÖÐ’·”„€¢ÛH$$žÑbž¼Sw[ý%7™j‘]jsÓ¦S)*srZßZAøÝ­'¸z‚>):¯Îœ.£{ÿ¿iè¬aÊÞ/°KÈU^ü¿(®ÂBçÔÄŠ÷c³\ žÀî-ÄΙÎnÓðîÇzV]{YÀ´EÁ¶-G\‹>°§¤¸¨2zKʼë«[« ܳÀ€‡õ’ëïöK®oÁ[sôÂ]ýÿ1”/ÐÓutÏNy°]Úm[n=1ö±DÜ6æ1õ‡6³·ËAtˆwç–ì䢋 *S(’ê  $x*üt˜zg¬ +*1‘6àKs#U¥ôøòA».4Òà6Ò™¶¹}׌i$¥* IBZRˆYãàtŸpØJmíiãºfK¥Í«_T)µ«Aˆ{Cuj|Ogö‰,ºØSjm××»ÞóAO>¼nzª ayÓk†Ù¶Í­=ÆÅ¶n8Ç,K¹®ûNÞeѹՊ%BDZCPã %IK -ö\JZB•ä…”„î¶ö·…wàìS·…g§©we㺻»ÖóC”z§"™D“X[o7QÌ$Te3Of:IaMw)ņˆí /ѪÇÏÊÞfݰ–ðð…qRn{›O±Þ°rev…Oýë®FRàÏn4v¢¼ë9õD²…)™M(ûþöºÎl©îÊÉÜN Ø$}ìÝ,Jʈ».KË)¢Ü¢µTST¸ðJh´–U ȱ[R¦;içÐÓêËQRôX»Öö³1µ¥Q¿²-ÝK P¨ñ*­Z­On,HL r·^yÕ% ¡#Ô©D>'U³pï_|ñ0 kZÛƒ…*ú²7ÁBÄ1r…BÖˆãuÚT©*„´ÊžB'û;â0c’Ç(SjQPú3öá÷U°–üp¥É¸Êÿ/â*5ÏdÝ·}µFöƪSêN>ìE„ÌGÙCÐ{ÛKŒ«„ºP¢°t`ËÌÈe#º—ZB´+ }A|F½UZ­2…L“[­Ô˜‡  ~\¹O%¶˜i *[‹Zˆ JR $ž@>§›÷Ü/O ÆÊÊößM»hwõ•*›;Ö"7jËa´-»½oF`ºšS>Ó3Òâ»P—XS\(©*›X^Þ¸­Ì?n[·¾Qvúª±DŽŠ­ß&,vMiâØ.Jò£¥-!T” v„9¡B^bS$-·[q¥hRHPP$Aƒ¨m6Òµ~Ÿ•2ÐÍ?È;@œágØ›ìïú)ˆ;¸ãŽxôç\op[­êw“·[›lí”c¬‘=Ì%uШ֕©mýG·*Ýð!Ï–kЬËj§Ä†å8Ó*„Ûhiµ¤­Ï0$,ßF¡>êsnàð>úè÷N~ÉYÐÀ3¦[°lúþ<¥Ñ¥QQX~QeøW7´C~|v¥<äXì¿M²ïÆœ>`ôl–ÀÈ_MwvÕú¶ç/ê*‹tÛ~ÏfÎ]-TÇ2ÝŽúB`¥ô&9Ym¯-äw%½ç¹Üâ‚Tç]ÊíãlÄ{×qùÊÒ°é2到ê7uÁžÔ‡È$4ÚŸZB×À*íO'€OÀ¬õ•|Xfʃ}㫾rÛµ¨êmf‹Pjd)ì+Ó­)Mºƒëê’AÔvß¾Ö÷yåœs½M T-‰ù@¬Ãƒd_m¬R®:}HEö¨è’ŽWN™û¿&RR¤òJµÞk‡º†Õ·–¶_Â4é–U“•™È,^v<¸q¦êf|¥FS­¥Cê3Z”R¶Tè÷ˆàö€˜—tÜ5`Fƒ2ü—lQ©Õ£Ré®ÕÜ2çIp5+EÎ:â’„6žTµ”‚OØ¥S_˜ý9…«€;–ÊIàñªß½Lã{bÊ…Ð2t*ÃpzR¬L³J%¦­ß¢(½³ä”ò–Üq!ñõt“Èp(:«šjésM—N©0•†¡"JÑ>ÎØiäÒœKϺ°±ÉVõt_a›C†ó%ae—c!Iî€ðGúüuòýØŸìU#úµ¯ÕÔ(é‘‘º’^ybrgªK«âû»5XŸsäw,–Ûr)ÈËhR·%¸ïìtˆÏ>B$¥Kl°Ñó q|ÎÝé¹zoS©î\Ûª. *”ÞÂâ¶Ü’Ð.% n¯ˆ€Hø ™`@{©Þ ¨» •Hc_Heõ6 ÛJž ÷«âíO |x6¢–y³,ùw2]©MuêFq¼êô—\‚Ú• ¢‹©â‰9mô•(‡SÂÁQàú4nÓmËz­áÒª]uJ )5K²« ¥tÔ¤EBäVfšÄ™2Ü#ºCݨ@ó*WHçÐk¸ø ÂÓ‚¡’ Ãi›ŠÖ¸â̶kí66‘!Hu z+ãê‘Ü)%%M”’ ñ£Fƒ]ÅÖ5•Eé}µ6(ö}."%ç &«)©í¶žåp8䥄¤w<¥’µ8}â£É<ëïÞ•‡.Vþ̺4G}»ÚÍÍó#¥^Є­•ò=ð9<ÈŸŸFcÂV¥¯yo¯;¢ï¶àUB1e›F@©CCá4çØ©8ü!ÞÜ_¼¶¾±Jõ dz8¾ûÝ41;N¼µ&5LXÉR‰ 0Ìé 4ÒŠ„6„!)‰JhÑ ó.O=c UŒ}¨mž["O”<Ï/è†2»;¾=¼úñðçUõâAªÔñ^ôðÅÍŒ*/Ûu+Êžª}ßP ¼¨o×"4ã¨óh¥RZ@R‚PáRSÜx“£Fƒ-»'\¯x–qö.®8©¶ÍMÚeR¥nK>d s¢Âeqe;\¶ãÌ­Sn)%M”¤¤‚¤Mý&Eµâ*° [’ObçÂ5®Fa,´Š³‘”¤Æ\žêi*Pl¯¸ („ñÉÑ£A|^ÙW(bóVñ6H¯ÚójLÏQ—nÖ„쨊yžèî-•$­£Éå %'æ×aêÏd٘ߣ†ß$c»F™@r‰\¶Er‹¸¦—I–-%>Py.¸íãÌ,+žãÉ£A¶ãÜwìý»7hZV5—I§õ¢ºu1¦#F-Ö©ÞYm´$%½©íà8|5¹ÔŠoˆ¡Å9=6êÀ2¤Ýöc‡Ùu†vScݶÚQm*p(¥¤4h#_BË‚½Oê×pÄ ÜÆ,ûAª¼[NÓfJÓL¢°'F¨‘Aò£#€kiHà|5rú4h?ÿÙphoronix-test-suite/pts-core/static/images/pts-158x82.png0000644000175000017500000000770111105171464023304 0ustar michaelmichael‰PNG  IHDRžR¥¯m´sBIT|dˆ pHYs66q²KjtEXtSoftwarewww.inkscape.org›î<>IDATxœí{ôTÕuÇ?ßDˆ@È$ŠZQ³b*ÖG0E]橦1šà#è¢6‰T5©‰¨i5¾ê²˜&VЀE­ DmS_(Z5*U‚‚Ö˜øÄŠZå÷Sðìþqΰ†q~sÏÌofîÌÏûYë®ßoîÝçÞ=÷î{çÜ}öÞGfF7#é`B†Øñfö`;ô)HcPÞ 4¿ÈÑE Òqy+PðÁ¤0¼‚\( ¯ B¯ A¦Nú:ð‘Z2ιI3fÌXÜìcO¼‚\( ¯  Ã+È…Âð r¡0¼‚\( ¯  Ã+È…Âð r¡0¼‚\( ¯  Ã+È…Âð r¡iA’†ŸÆÀ¡À;ÀZàyàq3{­YÇë$ö¶Æ‚RÕ¦ÃÏ6³;Út¬ºè—áIšü°° 'TÒ³ÀmÀÍÀB3{·?ÇïT$ ¦Äe/òûe¹†'iàào O¸zØ8*.«%Í.HOBI_Î>ž·.Lò(ÉI:X ü õ]%£€¿—ô÷’>ÜÏýåJ/püéøp0¤}*ñ#àI]‘’(iàô¼õè6j=YfŒ ¾Ü-©f>@ÞÄ'ó…yëÑT5 Ì®‰NåpZß¼ï¢FwÀ?6¸¿7€À ÀKÀG­€ãßzÙ˜Û >%މ?‰ýe™ÝWöù°Ävï¿î'8ÓÛEÇ–íØÈð$íÌ¡>Ïzp%0Xlfëª IOp6O%¼H¤ò=I›Ùeu´©ä[ýh[Î3§,’†“Ú< bf÷7I‡Aåï|`³Ä¶˜œafÏe ›ÙR`i|a9‘àzHíÃ-éßÍìÍDùv0Ø4Aîè`t&L8ÒÌÆÖ’ñÞߺtéÒ¤§ìÓ´7p`¢ÿff7&ÊoÀÌÖçHš Üì”Ðlp20­Þãµ%ÈÜgf·µ\“6`fÇ‘QIR/‰?ï.6pA¢«€=1ºrÌìI`àžÄ&'IÚ¢?Çl2cdj¹]Jé­ö`·ù^àkf¶¼7³5„§ì“ âÃ謑ª}Ù R»-8J†wt¢üwÍì·ÍT |•>•Å·cB'ðR‚LVÁÈ,.Ž|9Aö^3›Ý %ÌìqàŸDG_l… âùT ¬(¨ÀÁ ²§´X—ó€”ð¨/´XTþHyËž.é­V¦Ûì ÷;3K} h3{CÒÕÀñ¢)¾³J~üoí*¹»ô™­“t ppF›ó$=@sȽGý ÀÃföV“öÛŸLë×l\G¶á}BÒ&}9ªû`¾™ÝÞ½úb6Ù†Wb­ëóõJú !4ë:3ó-:NÓpÀ r·´Z‘È‚°ƒHÓ¹å˜Ù"BÈXÞ ®–ÅaÏŽÆ:ìYdŽL4ƒx§>› šâCk'”;ò)àzIÿÚA€÷áH+Åÿb«)ã…™Ž‰Õ‹CÇå­Gþ¸MRGúÙãffY?ͤ7AæCeÿ§è6¬A]’0³™¤ü´“‰ÀUÑÝq ‘>Unl«äSÆUû…™ |ŸÕIœ‘·•t«á•ûûR ¯ž0¬†1³KÛq¼:8ERÍÈ’vÓQѽ’Æ‘öt*ÛM1¼‰iT?f¶DÒŸß&D(O$-|ª• %Dö|§Ûu×]‡³qwè}t”á)n€ç+úœLh3QÒ°v9YãÛù,`VìÜïFx’†Óœ#Õ>Gša.éD3ëi±³X|¦–@§^JŠà’*Ÿ×µÂ½-k®…™½M ËHĨñYÀÆäç·J—zè˜>ž¤/’= #„Ú+0³^àÖ„vgJJ“î*b€ÅWH‹–é”qîÎ0¼ˆzN‚è:`A•õ)CzÛÞ:1´ìÜÑF®ZBGðÀgän2³ÕUÖßHšãlIY?IÝJJ^GËÝJ©änx’¾ ü8Qüüj+ÍlpEBûÁÀ|IÛ$¯›XŸ “ûõ.‘«"’Ž!Já3»·Æöi@Ê[ëVÀ1¹i ‘ò‹ÑΡϚäbx’†Kú9p2íÓj ˜Ù‹ôñD¬ÂÂ8æY1?¶«‘´)!X!‹¦áI"é8‚¸žõ+Íìѹ"ͯÁ•4Píû±dl×!i80øÓñŽ©šäÇ“´]û°9áé²=¡Å>Ôö·Uc¡úh&f¶6Æ¢ÝCz†×B¾ÇÅ’~Kð ®"¸'Þ®}ÄÌþPm'q >5/¹”ȇ*­fñ.pCK5ªƒÃPõd·×€ë© `fHšÌ£¾üˆµ|‰ÇÂ諱 ¡h§rƒ™½‘·%:æ-§ ëCcâw]˜Ù|à̦kÔ½¼G‡ÕðëTÃë!”Èh¸üƒ™ýø `MÓª{™af+óV¢œN4¼ç€‰f6¯¿;2³³ ªº*«É<ü]ÞJTÒi†w?0ÁÌšVsÄÌ{’V&c ñ ¡äH;"Rê¢S ïà“®é¾&3û! æÀšfï¿C¹›p§ä°´¼ ¯‡°£™ý¼Î\Ùº0³wÍì"BjäE„é®"=ÀÙÀ>förÞÊôE^†÷0¡ÞÝ83ûq; .šÙ3û!­óB5ÓjÝÆàr`'3ûI+oâfúxû6ÂÝ·–àý=° ¸½?§õ£˜¯®‹ÎßñÀ¶„Ž-ãR9œV« Æ{„„êvÑ ¼L{¸ÇÌR:‚Ã33KŽéZb¨úƒô£Xu¼èͪµÜ.ösÎÕ´žžžÇüåõë×× ¤õÞ—~¹Ž$cäHdû¹ÌÌòî  0 ƒ*È…Âð r¡0¼‚\( ¯ šjxιιι=š¹ß‚úpÎÉ9÷Iç܎ιŽ|¸Ô¥”sîPç\o\ÞrέpÎ]ïœ+Mž<˜P$¦cÒèúÂ9·Oü OüìœûaÙùèk¹¦™z'è4‰ĺ,.o;çêš Î9w‚s®¥C‹õVø¡\ÂA„/· !ÏávBÞj7ñ!f/¥àw_Ì–}¾˜PÚ· Ù97XD‚=x•0‰M½%3î¥l"EçÜf„´‚_yï›6=–e,ÞÌ03$M–d’v)[wz\7NÒ¨øÿÁqÛXIãJ²•‹¤IÚMÒ*ÛÆHÿßBÒÎÛ‡KÚCÒÈ*m?"i›ø¿“ôÙÊcÄüí$ ŠŸGÅÏ®Bn”¤1}}‡ Ùy’žÌÙAÒxIƒklß]Ò–eëÆJzVÒ/£Ž›÷Ñöóñüï‘qÎG×Z'i„¤mËÎßø¸ßïÆã«r­v¯\_ki†á]*é=I#Ë ïHI $­“ä%][¡èÖ’–Åv/JzGÒ92ÿ)ézIçJZ/éWqý`I ãºâþo*¿’¦IzIÒžqÿë%­‘t`™Ì~Q×âçÏE}§•Él%éUI“ûkxñâ¬ôš¤·$-/ÝqûŽqÝ+’þ éù²m+ã÷\/©WÒ%}cd<—‹$mև̒~]k¤%õ”Ýx½ñ\½ÿŸ·m¯S¤—ãÒ§Ñ7Íð$m+éuI÷—)i’VÇ‹?BÒaqÝÇË g™¤{$í$i¤)Qfj…á½.iޤ?Q¨ôޤ+¢Áýeü]Ò}ŠOÜJÉÆxn‚¿û3’¾Þ_ËŸGÇsõõŠvIzDÒæñºÎS˜â5ó\5úÆs¾sî.`%ða.´r.÷Þÿ4ŽÝ-ŽëJs¥ýaVëK½÷{ï×{ïgËÉûy 8Ê{ÿ´÷~]Wœ ,ôÞ/ðÞßAÈž:Ä9W^“Í€½÷÷xïßþ›ŒùÚ¼÷úHW;çÎŒº~/ûtÔÆ9·5ðyBU'#„dý!ó®Ä:`°WÔ¥2Ã- ïý̸`¾sîRç\«êóAŒx›ð¢ºøŒs.3U´QÃ{ŠÐ±Þ˜ä½¯Œû*Ÿï¬²"úøø·2ÇóÞ?ÄÓÞûòˆ‹ ¥õ«µÆÆ¹¥ozïËó R+³E(dxp¬÷¾!S¥Ìµ›ÑC Û²lþBÂM|—sî7ιqÌ{ÿáæ¾˜PŒqN£ûꋨßhBì_é;•Ž“™nÙ¨á]꽿Ò{ÿ˜÷¾ÞÉs¥ït §¡$L—š‡s±ô:¾ï%œ!Ù»fX’÷þyÂtûVlÚx1noçÜÎÀtÂl–ǧ:ç*»ð !áèï}oùR)轿™Pås᜔èF6p삵äRYK¨J €sn²‹:¾C¸7?þÊ­ tgz+–Ì̾¶WõÞ?íœûpšsnp¡îG©¤D?®pÎÍ"L¡t8ÁovdôŠ>°¹„þ邸noàJçÜxï}ÃIíÞûÕÎ¹Ó sü¡ÌÞÞûóã±.%”ßXB¨Üil<‰ô"`²sîKÀ£Þûgª|‡oŶ×&ªÙ—pÍ)ë3.ÎsÎ} |x:Cÿ7swG;çž øWê Þ윻œp-ÖŒx÷¾f®G½O¼—;é;]p]ÜþJ•uå+O 8ž'ú!Ï_ðÞ—×GYFxáØïý` ¡<Æe„R‡{ïË£ÿHx™ bÝÝeŸ×D½JX“ÇØx–Êã H³æW+ñ(}Ô©óÞ_1‘`à°q_è BÅøkYqxï)Û>¸ø%ÁXªñáe.!½à‚ã·¼èöUÀ BâÓöÀ—/:Ë+öS9UÖÉ„k8‡ØO÷ÞßJx:oA(w¡ßŸ ýÿ˜M*KÅ‹jkIEND®B`‚phoronix-test-suite/pts-core/static/images/pts-160x83.png0000644000175000017500000001012011726024364023270 0ustar michaelmichael‰PNG  IHDR SÉ šsBIT|dˆ pHYsJJŽØ°*tEXtSoftwarewww.inkscape.org›î<ÍIDATxœíyð]E•Ç?ß“v‘%(ag BXUHDÁRƒ¨KE´JŒÂ"ŒÀ(*›’A`,@‘Àˆ,jXDÈ@ &@X%„-„ CŸù£û%——ß/¯ßþ~á~ªnÕïÞÛ˹ýÎïv÷éÓçÊÝÈHü²F²…î>ºâ”ÔÉàn ÐVö¨‘fA')©ë¶%lJ,é*¥–t•a XÒãÆ;2„0¡Vº+®¸bívÔ_*àw íVýe\ÒUJ,é*¥–t•RKºJ©€%]¥TÀ’®R*`IW)°¤«” XÒUJ,é*¥–t•–¯KZXX x˜ ¼îîo·º®„¤ÀpàCÄöQ‡ª^èî—v¨®ºiJ%­Œö>lGlܾÒΞ&w÷ù@ßPIÛÇG[uIŒ·€K% NÆdfÛ(œ<'ið#wŸÝˆ½Š¤ŸñóÀ îJÓÛÔ5”´¤ïÓ“ÈW¾¾Ø8˜!éI«5QVÏ iàq`¥òÕ$K% ‘t0ƒøæÒBÖΞ–ôo-,·ã$ùC?Ã’e©©€’6~œ¬ÑFY†—IºVÒªm¬§-H:¸„ò­WËU@I»{uFþ˜”ÆQI®§4kÕM¿ &é0à`ÓΉ³„QÀdI;t¡îFø/¢Ù©¤NúT@I»×Ýì ‡·JÚ¨‹2ÔDÒÞÀ?v[ŽÊ2f˜4æ»hfVêÀëÀJÄIF£ n–4ÚÝ6QÎ I£›È_äIwŸU8ÿ÷:ò."ÎgÛ¨ÌëP= ñ>”´2ð+êïvçg7÷3Ýýo©ÌUÍ€ý‰Ù}«ë­ÁÀUÀÑuÊTdð»&ò9ø€$>™™ïJà$w«Er¬T+‰Ԏ³Rd>pp^ ëî ˆvÃéÀÅ’6#Ψ?GþŒñ(I׺ûÍuÈÖ v&ÏúSw×naÚ$9rx­tƒ zuòäÉósÊ\¢€’ÖN­Cž{€ÏºûËuäÁÝ_¾(éBbT«­3³ž#i¢»¿WO}mfóŒ4ó€o´[N0zôè•çÎûlFÒ#ˆ=iMŠ“o“¿Aùr`¿z•¯ˆ»OöîÎ̲=±ûë%r&HS>èŽËÃ`‰ë„Ì\èîÛ6,Õò¹…¼6ܸ¸Õ•KZ¼ ×Îzd?à{ÕËÜÈÛŸÚôªGä˜XŠ¶ÈœEï•Úmºq÷7‰?SÛYOƒì\“l¾=E/ºç¸â•.×߭펭îþ qûB=3ôNq$qlØSô¢æÌÊ— Ü}>ÑtS‹ŽÌœÝýmw?‚8+}¬uÖÁ™)˜@ÏЋŸi84#Í_ªÎ§QÛvx0Ñf×ÜýI#‰6ÂCˆÝó¦Ä7ñ*’£ŠŸ®îDe£FOgí)LñSvÌH:¥êüÿˆ¡A–Ç!’ÔÉp ©®Éé8£r=yô´b<6ˆèOù ¢“oÎl÷(:¤€ÀxjŒé{­ Îu »³ê|RFžMˆ3Õ®ãî‹Ü}a Žyîþˆ»_Dô—|:£ú$õ̾žQ@I›’çóxòª.r7ðnFÞïHjeT‡ž!-¿—‘tQY{‚žQ@âÞÚœ±Ñ•ÕÒjDÎráÀ·ê’jáî÷’g‹ì™Mÿ=¡€’N"¯{\@ÿã—K2«;MRÎDg ’c‡Ü°íRdÒu”tð½Ìä¹ûk}Ýp÷;;rª®–´ofÍ2ÒÌi»™tU% Ü@ÞöÌÙÀ¹5Ò|“¼¥¹¡Àéͻ¢Hä¸urm¹tE%m+i"Q¡re8·Ö¦nwŸü<³¼ÁÀ…’î‘TË„3Pø1y{{rfË¡c ˜b î'é'D÷®ƒëÈ> øafÚñ@=γî•t‡¤ÒÆù…¤a’n$/FÍÃîþ×vË”K®!ú«’‰12”8ãÚ”q!gc5s€O§ 5q÷—%}øõ­8쟎‹%Í$n8šTǤù»÷æCÒ/hmÏåQ1D ÿerSûÄ©Ÿ\ü¶JÑ?}¡®ÍPîþ ¤ãˆ¾aX:ú¢ÖxÑK¹™Lè¶Eº> ®Á7ݽÖ&¥>q÷ëYm~ òßîÞIßΚôª.Np÷ š)ÄÝÏ&î#ÎY%YÑyšhìï)zQßhÕÇUÜ}Ñ+¸Oûá„9À¡½¸…³×ða`÷å ò!-QíF~ ¤‰9Àî^íÂÖôŠþ•¸¾›»ÏhGîþ¼»ïG4ÿü¹uô Ó€=ZýÝJº­€oÃÂmíîW¦Í=m%…Ù™86ìÉ·B ˜OŒd1ªáTZA7R_#Úèn~kßk%IÑ'$íFÜ/±1:ÿ@v×z”ßû²fb7v’\¼Še ²µpâìs>qw:0ÕÝ[£¥%¸ûCÄo¡6q'FXX“e²V,Ã/Ó¹ì@œ´Íf´[é^zé%:thN½¬ð¼=Cr\Ô7ìÏ ¥¤¤º=,ù€S*`IW)°¤«” XÒUJ,é*u™ Ìl0K#8ðzὪ4¿ !œÞÛ‡™­¬Bh8¢h*cÍÉÞ !¼Ùh`fƒˆ›üGÏÓBuÙ\Íl] „Úöy±z߀;ã²Ì$z/0³éfö¯…4Û‘ô²øðB“eœÈÒ6éïèXH3[hÛœB\¹ xÇÌê òkÚE¡Ñ.ø D‡Í}‰FЫ̬g6;×ÁÀØ&˸X§p\E4¼¯Ød˜Ù±fv}FÒ³ˆ{ · !lO܆ù)¢›[=œNÁ…ËÌ>afw˜YËBÝ5ª€óB¯„þœ–®í½Láf››Ù'ͬOa3ÛÈÌ3³¦.£xo-3ÛÓÌÖ0³ÕÌì3[³pˆ™íÊ_§²w2³-Óß›™ÙA}¼Þ¢ð3ÛÁÌFõQÖfÖgÔ®¢Â[•ƒ¸úãÅk!„w e™™2³£Ìl“~Úe+3ûŒ™}¬"³™mNŒ¸5&µËî}åMŒ!ÌH2¾B¸=„°8•µz*cIˆŽÔž{¦n·ÂLRÀP3[ŸøE…ý=SÚU ùW2³}ÌìÈôÎÆ3Ž ÜI#%¹¤£ÝtíKéÚ?¤ó¿HºRÒ$ýMÒ\IoJÚªg¤R¾Ç$-’4SÒˆBšÑéþq)ÿlI[§{‡Jš/é IÏJ ’ÆWò¦4OHºZÒ…9fKÚ¦æÛ’ÎOu_¸¶»¤w%íS,¿¿CÒå’ÞèçÞÚ’ž”ôº¤éI¦ ÷‡HzDÒ+’~Ÿžodºwš¤9’KzNÒSË‘á»é™éçþ®é9÷/\Û$]û§Âµ{%ÝRh›×Rš’ •ßc‹$ó ’^JïœÓ^M) ¤ Óý†¤Õ 8OÒõ’†JZCÒ«’N/<ØyIƤóÍ$Ý'i†¤•ªðEI{òn›Ê¿$•=XÒ×SÚëpž¤_$9VO sf Xm¡¤]$­šžç‚œÆÌPÀ›·®¢È5I-Ý+i¤5 y¬ð÷ù’^ÌaI·¦6¹UÒðf0“Ò¬_UÞ#’®M¿ÅJ’&IúmN{5ÚŸbfÏgÒ{…Š ÐS€±!„9©ûy Y¸ÿà¾ÂïB/ÇN®Jpbêê+Lüšû÷Cï¤nåGÄðêïÈ=“ä˜Gô«.¿šS‰7¤rßcé0£aÒ0ä`b ›µ‰q'[±4šÁlâN¾/WºÞBÝ.j!„ÙĘ„ß"v™›Ù§š}†¾HÜ‘Ä ËúÀzÄçmf5õ«Q|¸èe¼}¡ÚÃeze¼‘XcÚÌÖ&*ÚªòTΫÇ6Õ{X? ¼BXâçBx¸¿¼ÓCÅøÖ5áɬ4–8“ÿ@ä!૾‘Jy ˜dõµo8¹Ü{¹I0 óÍœ¹çì½×^kŸóµ×ÚûÞ+3#tke?;âJ:pQòEÎÆ1b´!$rUêÖÊ~`sH¶ë‹ÕU«bó­eXŒ-EVrkâìR°9@ŠÐýc‚ÇØ›‘Üš8»”$Qb§<Æ^ƒ]È­Û*ŽÄ>0‹LLð{‘[·U%jÈNìb‚Çhóh ·n©:ŠúD.Ž˜à1Ú4ˆ­ºÄAM” £Í"¡Û*û’¨›Ó b§Gðœà­…ÎÁŽý[Qg6ˆÛÒ1G› ÀW­cNËQP>«‰¼Ø96ñƒÇ~xkfßDꮞ¦H*3³Úæ £Ù˜jfÓ#ö< Ì‘4È̶²-mföôÿÚ†¦ –ÅY=¸Ö€Ýl–æC쀱ÀÁÀ•Qb˜Ù&à7@à,I£%M‘T-i±¤Y’.“vÎ ’ %]-é%I %=,éÐHýI?t•¤Ù’*$•T¸[{…φiYÒ ’ž z*$Ô”t¯¤!’•ôš¤›%õnt¥RI“$ýSÒ"I3BBY°y¤{$•EdÇJº^ÒIÓƒŽ ’ŠÃøª$=-锈L‡`W¥¤·$½(éÂH}WI5’Ž c;'bËY’þ,iž¤'ÒÆ{»¤»ÃyÏp?Ž”tŸ¤WƒÎãÒÆÞKÒ’æ‡ñMívÝ@”Š$—4'Üï'£ýI:MÒ]#3%•Ft<˜®£‘‚âÂBF ˆ\kHÚpÓýoˆ³o±J÷ÌlM¦J3[ŠOwG†¢ÀPàQ`°˜Ü{¸˜܉¿Õ‘úÀ*`ð0>k<ŒÎdƒ¤’®~Üaf…ò“€yxØò;SécI°±øm°;ú¢ß¼ ܼòðÐå&à*àY ×'„qmþ.©sIà/è<\L–tI¨o f €è,5øøJN‘Ô/Ô¤œH!ð#<ŒûÏazEm—ÔX º‡ÏMìŒýŸÀÃ…(>n¢m˜¿îK%]‡.£ðé~+¾dù`šÈûMè~ °½9vµ£ñÐå"|eª#âå‹ñiÐ;=WjêðÐ-ìÀC•t~á³v6ÔûfªÈ5t“ÕýcóMšçihã÷’ùüàaþˆ{¸çsôq&C~†Ç;€Nf65íhéútj3+åÑގŧ⨞7›Ðç›Àyy$³{§óÍlš™½cfoà3h^0³`SÒ;–§Hʇ7ËÂçi©‚tžŠÏ†Ù°"›Ž¬ž;ƒn…I»ò2pWy³õ’.&¥’ž>¾ü;Ï3³-±c%=†j4ž,\¦öõ’&WKŒOÝ®f6¾‰æ,iŸp~> ¯Ã“6pow°XÒKxrÔÏ æç©ãMÒP3ËÂì·Izw¦ ¡¡¤nÀõÀMfö¤G€û$•ãÏþBܓ߼Dt$S:ò[ïh!Ìlp0å®Ç¯j ¯™ÍNY‡{ó!81N‰îŠ™Ù 8éVá®ßIa1ð^ZŸ²sU Ѓ€ËÂñC`p‚™}ô|‚¿|Ïà«?ÅcÃÔ ´>ô§w„² ¡ñØý)œ,çàyƒáaÏ\<¡â|–‹æ¥Õ¯d§§Káuà“p^…;…Žø=¬ÆW–†úíAï×ùM¡ì›`÷¶`ëà¼Ðf¾ªC>¶‡¼¥wl}ðg´$´3. */ class pts_DetailedSystemComponentTable extends pts_SideViewTable { public function __construct(&$result_file, $log_location, $intent = false) { if(!is_readable($log_location)) { return false; } if($intent == false) { $intent = -1; $intent = pts_result_file_analyzer::analyze_result_file_intent($result_file, $intent, true); } if(!isset($intent[0])) { return false; } if(is_array($intent[0]) && in_array('Processor', $intent[0])) { $component_report = 'Processor'; } else if(is_array($intent[0]) && in_array('Graphics', $intent[0])) { $component_report = 'Graphics'; } else { return false; } $this->rows = array(); $this->columns = array(); $this->table_data = array(); $logs_to_capture = array(); if($component_report == 'Processor') { $this->columns = array('Model Name', 'Core Count', 'Thread Count', 'L2 Cache', 'Cache Size', 'Virtualization', 'Features', 'Flags'); $logs_to_capture = array('cpuinfo', 'lscpu'); } else if($component_report == 'Graphics') { $this->columns = array('OpenGL Renderer', 'OpenGL Version', 'GLSL Version', 'OpenGL Extensions'); $logs_to_capture = array('glxinfo'); } if(is_dir($log_location)) { foreach($result_file->get_system_identifiers() as $system_identifier) { phodevi::$vfs->clear_cache(); foreach($logs_to_capture as $log_file_name) { if(is_file($log_location . $system_identifier . '/' . $log_file_name)) { phodevi::$vfs->set_cache_item($log_file_name, file_get_contents($log_location . $system_identifier . '/' . $log_file_name)); } } if(count(phodevi::$vfs->cache_index()) > 0) { switch($component_report) { case 'Processor': $this->generate_processor_data($result_file, $system_identifier); break; case 'Graphics': $this->generate_graphics_data($result_file, $system_identifier); break; } } phodevi::$vfs->clear_cache(); } } if(empty($this->rows)) { return false; } foreach(array(array('Processor', 'Flags', 'Common CPU Flags'), array('Graphics', 'OpenGL Extensions', 'Common OpenGL Extensions')) as $set) { if($component_report == $set[0]) { $flags_data = $this->table_data[array_search($set[1], $this->columns)]; foreach($flags_data as $i => &$flags) { $flags = explode(' ', $flags); sort($flags); } if($flags_data == null || count($flags_data) < 2) { continue; } $intersect = call_user_func_array('array_intersect', $flags_data); sort($intersect); foreach($flags_data as $i => &$flags) { $flags = array_diff($flags, $intersect); $flags = implode(' ', $flags); } $this->table_data[array_search($set[1], $this->columns)] = $flags_data; $intersect_label = $set[2]; break; } } parent::__construct($this->rows, $this->columns, $this->table_data); if(isset($intersect) && !empty($intersect)) { $this->addTestNote(trim(implode(' ', $intersect)), null, $intersect_label); } } protected function generate_processor_data(&$result_file, $system_identifier) { array_push($this->rows, $system_identifier); $rows_index = count($this->rows) - 1; foreach($this->columns as $i => $cpuinfo_item) { switch($cpuinfo_item) { case 'Features': $line = phodevi_cpu::instruction_set_extensions(); break; case 'Core Count': $line = phodevi_cpu::cpuinfo_core_count(); break; case 'Thread Count': $line = phodevi_cpu::cpuinfo_thread_count(); break; case 'L2 Cache': $line = phodevi_cpu::lscpu_l2_cache(); break; case 'Virtualization': $line = phodevi_cpu::virtualization_technology(); break; default: $line = phodevi_cpu::read_cpuinfo_line(strtolower($cpuinfo_item), false); break; } if($line) { $line = pts_strings::strip_string($line); } $this->table_data[$i][$rows_index] = $line; } } protected function generate_graphics_data(&$result_file, $system_identifier) { array_push($this->rows, $system_identifier); $rows_index = count($this->rows) - 1; foreach($this->columns as $i => $cpuinfo_item) { switch($cpuinfo_item) { case 'OpenGL Renderer': $line = phodevi_parser::read_glx_renderer(); break; case 'OpenGL Version': $line = phodevi_parser::software_glxinfo_version(); break; case 'GLSL Version': $line = phodevi_parser::software_glxinfo_glsl_version(); break; case 'OpenGL Extensions': $line = phodevi_parser::software_glxinfo_opengl_extensions(); break; } $this->table_data[$i][$rows_index] = $line; } } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_TestCountPassGraph.php0000644000175000017500000001613611704717125027106 0ustar michaelmichael. */ class pts_TestCountPassGraph extends pts_Graph { public function __construct(&$result_object, &$result_file = null) { parent::__construct($result_object, $result_file); $this->i['hide_y_title'] = true; $this->i['graph_value_type'] = 'ABSTRACT'; $this->i['hide_graph_identifiers'] = true; } protected function render_graph_passcount() { $identifier_count = count($this->graph_identifiers); $vertical_border = 20; $horizontal_border = 14; $heading_height = 24; $graph_width = $this->i['graph_left_end'] - $this->i['left_start'] - ($horizontal_border * 2); $graph_height = $this->i['graph_top_end'] - $this->i['top_start'] - ($vertical_border * 2) - $heading_height; $line_height = floor($graph_height / $identifier_count); $paint_color = $this->get_paint_color('PASS_COUNT'); $main_width = floor($graph_width * .24); $main_font_size = self::$c['size']['bars']; $main_greatest_length = pts_strings::find_longest_string($this->graph_identifiers); $width = $main_width - 8; $height = $line_height - 4; $main_font_size = $this->text_size_bounds($main_greatest_length, $main_font_size, 4, $width, $height); if(($new_size = $this->text_string_width($main_greatest_length, $main_font_size)) < ($main_width - 12)) { $main_width = $new_size + 10; } $identifiers_total_width = $graph_width - $main_width - 2; $headings = pts_strings::comma_explode($this->graph_y_title); $identifiers_width = floor($identifiers_total_width / count($headings)); $headings_font_size = self::$c['size']['bars']; while(($this->text_string_width(pts_strings::find_longest_string($headings), $headings_font_size) > ($identifiers_width - 2)) || $this->text_string_height($this->i['graph_max_value'], $headings_font_size) > ($line_height - 4)) { $headings_font_size -= 0.5; } for($j = 0; $j < count($this->graph_data[0]); $j++) { $results = array_reverse(pts_strings::comma_explode($this->graph_data[0][$j])); $line_ttf_height = $this->text_string_height('AZ@![]()@|_', self::$c['size']['bars']); for($i = 0; $i < count($headings) && $i < count($results); $i++) { $this_bottom_end = $this->i['top_start'] + $vertical_border + (($j + 1) * $line_height) + $heading_height + 1; if($this_bottom_end >= $this->i['graph_top_end'] - $vertical_border) { $this_bottom_end = $this->i['graph_top_end'] - $vertical_border - 1; } else if($j == (count($this->graph_data[0]) - 1) && $this_bottom_end < $this->i['graph_top_end'] - $vertical_border) { $this_bottom_end = $this->i['graph_top_end'] - $vertical_border - 1; } $x = $this->i['graph_left_end'] - $horizontal_border - ($i * $identifiers_width); $y = $this->i['top_start'] + $vertical_border + ($j * $line_height) + $heading_height; $this->svg_dom->add_element('rect', array('x' => $x, 'y' => $y, 'width' => $identifiers_width, 'height' => ($this_bottom_end - $y), 'fill' => $paint_color)); $x = $this->i['graph_left_end'] - $horizontal_border - ($i * $identifiers_width) - ($identifiers_width * 0.5); $y = $this->i['top_start'] + $vertical_border + ($j * $line_height) + $heading_height + ($line_height / 2) - ($line_ttf_height / 2); $this->svg_dom->add_text_element($results[$i], array('x' => $x, 'y' => $y, 'font-size' => self::$c['size']['bars'], 'fill' => self::$c['color']['body_text'], 'text-anchor' => 'middle', 'dominant-baseline' => 'text-before-edge')); } } $headings = array_reverse($headings); $line_ttf_height = $this->text_string_height('AZ@![]()@|_', $headings_font_size); for($i = 0; $i < count($headings); $i++) { $this->svg_dom->draw_svg_line($this->i['graph_left_end'] - $horizontal_border - (($i + 1) * $identifiers_width), $this->i['top_start'] + $vertical_border, $this->i['graph_left_end'] - $horizontal_border - (($i + 1) * $identifiers_width), $this->i['graph_top_end'] - $vertical_border, self::$c['color']['body_light']); $x = $this->i['graph_left_end'] - $horizontal_border - ($i * $identifiers_width) - ($identifiers_width * 0.5); $y = $this->i['top_start'] + $vertical_border + ($heading_height / 2) - ($line_ttf_height / 2); $this->svg_dom->add_text_element($headings[$i], array('x' => 0.5, 'y' => 0, 'font-size' => $headings_font_size, 'fill' => self::$c['color']['headers'], 'text-anchor' => 'middle', 'dominant-baseline' => 'text-before-edge')); } $line_ttf_height = $this->text_string_height('AZ@![]()@|_', $main_font_size); for($i = 0; $i < count($this->graph_identifiers); $i++) { $this->svg_dom->draw_svg_line($this->i['left_start'] + $horizontal_border, $this->i['top_start'] + $vertical_border + ($i * $line_height) + $heading_height, $this->i['graph_left_end'] - $horizontal_border, $this->i['top_start'] + $vertical_border + ($i * $line_height) + $heading_height, self::$c['color']['body_light']); $x = $this->i['left_start'] + $horizontal_border + $main_width; $y = $this->i['top_start'] + $vertical_border + ($i * $line_height) + $heading_height + ($line_height / 2) - 2; $this->svg_dom->add_text_element($this->graph_identifiers[$i], array('x' => $x, 'y' => $y, 'font-size' => $main_font_size, 'fill' => self::$c['color']['headers'], 'text-anchor' => 'end', 'dominant-baseline' => 'middle')); } $this->svg_dom->draw_svg_line($this->i['left_start'] + $horizontal_border, $this->i['top_start'] + $vertical_border, $this->i['graph_left_end'] - $horizontal_border, $this->i['top_start'] + $vertical_border, self::$c['color']['body_light']); $this->svg_dom->draw_svg_line($this->i['left_start'] + $horizontal_border, $this->i['top_start'] + $vertical_border, $this->i['left_start'] + $horizontal_border, $this->i['graph_top_end'] - $vertical_border, self::$c['color']['body_light']); $this->svg_dom->draw_svg_line($this->i['graph_left_end'] - $horizontal_border, $this->i['top_start'] + $vertical_border, $this->i['graph_left_end'] - $horizontal_border, $this->i['graph_top_end'] - $vertical_border, self::$c['color']['body_light']); $this->svg_dom->draw_svg_line($this->i['left_start'] + $horizontal_border, $this->i['graph_top_end'] - $vertical_border, $this->i['graph_left_end'] - $horizontal_border, $this->i['graph_top_end'] - $vertical_border, self::$c['color']['body_light']); } protected function render_graph_result() { $this->render_graph_passcount(); } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_CandleStickGraph.php0000644000175000017500000000646311714017354026513 0ustar michaelmichael. */ class pts_CandleStickGraph extends pts_VerticalBarGraph { protected function render_graph_candle_sticks() { $bar_count = count($this->graph_data_raw); $bar_width = floor($this->i['identifier_width'] / $bar_count) - ($bar_count * 16); 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)); for($i = 0; $i < count($this->graph_data_raw[$i_o]); $i++) { $run_values_r = pts_strings::colon_explode($this->graph_data_raw[$i_o][$i]); $start_value = $run_values_r[0]; $end_value = $run_values_r[(count($run_values_r) - 1)]; $average_value = array_sum($run_values_r) / count($run_values_r); sort($run_values_r); $low_value = $run_values_r[0]; $high_value = $run_values_r[(count($run_values_r) - 1)]; $px_bound_left = $this->i['left_start'] + ($this->i['identifier_width'] * $i) + ($bar_width * $i_o) + 8; $px_bound_center = $px_bound_left + round($bar_width / 2); $top_diff = $this->i['graph_top_end'] - $this->i['top_start']; $plot_wick_lowest = $this->i['graph_top_end'] + 1 - round(($low_value / $this->i['graph_max_value']) * $top_diff); $plot_wick_highest = $this->i['graph_top_end'] + 1 - round(($high_value / $this->i['graph_max_value']) * $top_diff); $plot_body_start = $this->i['graph_top_end'] + 1 - round(($start_value / $this->i['graph_max_value']) * $top_diff); $plot_body_end = $this->i['graph_top_end'] + 1 - round(($end_value / $this->i['graph_max_value']) * $top_diff); if($start_value > $end_value) { $body_color = self::$c['color']['body']; $plot_body_high = $plot_body_start; $plot_body_low = $plot_body_end; } else { $body_color = $paint_color; $plot_body_low = $plot_body_start; $plot_body_high = $plot_body_end; } $this->svg_dom->draw_svg_line($px_bound_center, $plot_wick_lowest, $px_bound_center, $plot_wick_highest, self::$c['color']['body_light'], 1); $this->svg_dom->add_element('rect', array('x' => $px_bound_left, 'y' => $plot_body_low, 'width' => $bar_width, 'height' => ($plot_body_high - $plot_body_low), 'fill' => $body_color, 'stroke' => self::$c['color']['body_light'], 'stroke-width' => 1)); } } } protected function render_graph_result() { if(count($this->graph_data_raw) == 0 || empty($this->graph_data_raw[0])) { $this->render_graph_bars(); } else { $this->render_graph_candle_sticks(); } } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_PieChart.php0000644000175000017500000001150511713776002025036 0ustar michaelmichael. */ class pts_PieChart extends pts_Graph { public function __construct(&$result_object, &$result_file = null) { parent::__construct($result_object, $result_file); $this->i['graph_value_type'] = 'ABSTRACT'; $this->i['hide_graph_identifiers'] = false; $this->i['identifier_width'] = 0; $this->update_graph_dimensions($this->i['graph_width'], $this->i['graph_height'] + 100); } protected function render_graph_pre_init() { $pie_slices = count($this->graph_identifiers); $this->i['pie_sum'] = 0; for($i = 0; $i < $pie_slices; $i++) { $this->i['pie_sum'] += $this->graph_data[0][$i]; } if($pie_slices > 8) { $this->update_graph_dimensions($this->i['graph_width'], $this->i['graph_height'] + 100); } } protected function render_graph_identifiers() { $key_strings = array(); foreach(array_keys($this->graph_identifiers) as $i) { $percent = pts_math::set_precision($this->graph_data[0][$i] / $this->i['pie_sum'] * 100, 2); array_push($key_strings, '[' . $percent . "%]"); //array_push($key_strings, '[' . $this->graph_data[0][$i] . ' / ' . $percent . "%]"); } $key_count = count($key_strings); $key_item_width = 18 + $this->text_string_width(pts_strings::find_longest_string($this->graph_identifiers), self::$c['size']['key']); $key_item_width_value = 12 + $this->text_string_width(pts_strings::find_longest_string($key_strings), self::$c['size']['key']); $keys_per_line = floor(($this->i['graph_left_end'] - $this->i['left_start'] - 14) / ($key_item_width + $key_item_width_value)); if($keys_per_line < 1) { $keys_per_line = 1; } $key_line_height = 14; $this->i['top_start'] += 12; $c_y = $this->i['top_start'] - $key_line_height - 5; //$this->reset_paint_index(); for($i = 0; $i < $key_count; $i++) { $this_color = $this->get_paint_color($i); if($i > 0 && $i % $keys_per_line == 0) { $c_y += $key_line_height; $this->i['top_start'] += $key_line_height; } $c_x = $this->i['left_start'] + 13 + (($key_item_width + $key_item_width_value) * ($i % $keys_per_line)); $this->svg_dom->add_element('rect', array('x' => ($c_x - 13), 'y' => ($c_y - 5), 'width' => 10, 'height' => 10, 'fill' => $this_color, 'stroke' => self::$c['color']['notches'], 'stroke-width' => 1)); $this->svg_dom->add_text_element($this->graph_identifiers[$i], array('x' => $c_x, 'y' => $c_y, 'font-size' => self::$c['size']['key'], 'fill' => $this_color, 'text-anchor' => 'start', 'dominant-baseline' => 'middle')); $this->svg_dom->add_text_element($key_strings[$i], array('x' => ($c_x + $key_item_width + 30), 'y' => $c_y, 'font-size' => self::$c['size']['key'], 'fill' => $this_color, 'text-anchor' => 'end', 'dominant-baseline' => 'middle')); } } 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')); } } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_HorizontalBoxPlotGraph.php0000644000175000017500000001137011714017537027764 0ustar michaelmichael. */ class pts_HorizontalBoxPlotGraph extends pts_HorizontalBarGraph { protected function render_graph_bars() { $bar_count = count($this->graph_data); $separator_height = ($a = (6 - (floor($bar_count / 2) * 2))) > 0 ? $a : 0; $multi_way = $this->is_multi_way_comparison && count($this->graph_data) > 1; $bar_height = floor(($this->i['identifier_height'] - ($multi_way ? 4 : 0) - $separator_height - ($bar_count * $separator_height)) / $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) { $min_value = round(min($this->graph_data[$i_o][$i]), 2); $avg_value = round(array_sum($this->graph_data[$i_o][$i]) / count($this->graph_data[$i_o][$i]), 2); $max_value = round(max($this->graph_data[$i_o][$i]), 2); $px_bound_top = $this->i['top_start'] + ($multi_way ? 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); $value = 'Min: ' . $min_value . ' / Avg: ' . $avg_value . ' / Max: ' . $max_value; $title_tooltip = $this->graph_identifiers[$i] . ': ' . $value; $value_end_left = max($this->i['left_start'] + round(($min_value / $this->i['graph_max_value']) * ($this->i['graph_left_end'] - $this->i['left_start'])), 1); $value_end_right = $this->i['left_start'] + round(($max_value / $this->i['graph_max_value']) * ($this->i['graph_left_end'] - $this->i['left_start'])); $box_color = in_array($this->graph_identifiers[$i], $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($this->graph_data[$i_o][$i], 0.25) / $this->i['graph_max_value']) * ($this->i['graph_left_end'] - $this->i['left_start'])); $box_middle = $this->i['left_start'] + round((pts_math::find_percentile($this->graph_data[$i_o][$i], 0.5) / $this->i['graph_max_value']) * ($this->i['graph_left_end'] - $this->i['left_start'])); $box_right = $this->i['left_start'] + round((pts_math::find_percentile($this->graph_data[$i_o][$i], 0.75) / $this->i['graph_max_value']) * ($this->i['graph_left_end'] - $this->i['left_start'])); $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, 'stroke' => self::$c['color']['body_light'], 'stroke-width' => 1, 'xlink:title' => $title_tooltip)); $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)); } } // 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); } protected function maximum_graph_value() { $real_maximum = 0; foreach($this->graph_data as &$data_r) { $real_maximum = max($real_maximum, max(max($data_r))); } $maximum = (floor(round($real_maximum * 1.285) / $this->i['mark_count']) + 1) * $this->i['mark_count']; $maximum = round(ceil($maximum / $this->i['mark_count']), (0 - strlen($maximum) + 2)) * $this->i['mark_count']; return $maximum; } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_ScatterPlot.php0000644000175000017500000001611611714020335025576 0ustar michaelmichael. */ class pts_ScatterPlot extends pts_Graph { public function __construct(&$result_object, &$result_file = null) { parent::__construct($result_object, $result_file); $this->i['show_graph_key'] = true; $this->i['show_background_lines'] = true; $this->i['iveland_view'] = true; $this->i['min_time'] = 0; $this->i['max_time'] = 0; $this->i['spread_time'] = 0; $this->i['plot_overview_text'] = true; //$this->i['graph_width'] = 1400; //$this->i['graph_height'] = 600; //$this->update_graph_dimensions(-1, -1, true); } protected function maximum_graph_value() { $maximum = 0; foreach($this->graph_data as &$data_r) { $maximum = max(max($data_r), $maximum); } $maximum = (floor(round($maximum * 1.2) / $this->i['mark_count']) + 1) * $this->i['mark_count']; $maximum = round(ceil($maximum / $this->i['mark_count']), (0 - strlen($maximum) + 2)) * $this->i['mark_count']; return $maximum; } protected function render_graph_pre_init() { $this->i['min_time'] = min($this->graph_identifiers); $this->i['max_time'] = max($this->graph_identifiers); $this->i['spread_time'] = $this->i['max_time'] - $this->i['min_time']; // Do some common work to this object /* $graph_identifiers_count = count($this->graph_identifiers); $identifier_count = $graph_identifiers_count > 1 ? $graph_identifiers_count : count($this->graph_data[0]); $this->i['identifier_width'] = ($this->i['graph_left_end'] - $this->i['left_start']) / ($identifier_count + 1); $longest_string = pts_strings::find_longest_string($this->graph_identifiers); $this->i['identifier_size'] = $this->text_size_bounds($longest_string, $this->i['identifier_size'], $this->i['min_identifier_size'], $this->i['identifier_width'] - 4); if($this->i['identifier_size'] <= $this->i['min_identifier_size']) { list($text_width, $text_height) = pts_svg_dom::estimate_text_dimensions($longest_string, $this->i['min_identifier_size'] + 0.5); $this->i['bottom_offset'] += $text_width; $this->update_graph_dimensions($this->i['graph_width'], $this->i['graph_height'] + $text_width); if(($text_height + 4) > $this->i['identifier_width'] && $graph_identifiers_count > 3) { // Show the identifiers as frequently as they will fit $this->i['display_select_identifiers'] = ceil(($text_height + 4) / $this->i['identifier_width']); } } */ } protected function render_graph_result() { $bar_count = count($this->graph_data); 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)); $points = array(); foreach(array_keys($this->graph_data[$i_o]) as $i) { $key_time = $this->graph_identifiers[$i]; $value = $this->graph_data[$i_o][$i]; if($value <= 0) { continue; } $x = $this->i['left_start'] + (($this->i['graph_left_end'] - $this->i['left_start']) * (($key_time - $this->i['min_time']) / $this->i['spread_time'])); $y = $this->i['graph_top_end'] + 1 - round(($value / $this->i['graph_max_value']) * ($this->i['graph_top_end'] - $this->i['top_start'])); $this->svg_dom->add_element('ellipse', array('cx' => $x, 'cy' => $y, 'rx' = 2, 'ry' = 2, 'fill' => $paint_color, 'stroke' => $paint_color, 'stroke-width' => 1)); array_push($points, array($x, $y)); } $sum_x = 0; $sum_y = 0; $sum_x_sq = 0; $sum_y_sq = 0; $sum_xy = 0; foreach($points as $point_set) { $sum_x += $point_set[0]; $sum_y += $point_set[1]; $sum_x_sq += pow($point_set[0], 2); $sum_y_sq += pow($point_set[1], 2); $sum_xy += $point_set[0] * $point_set[1]; } $point_count = count($points); $mean_x = $sum_x / $point_count; $mean_y = $sum_y / $point_count; $denominator = ($sum_x_sq - $mean_x * $sum_x); $m = ($sum_x_sq - $mean_x * $sum_x) == 0 ? 0 : ($sum_xy - $mean_y * $sum_x) / $denominator; $b = $mean_y - $mean_x * $m; $pearson_num = $sum_xy - ($sum_x * $sum_y / $point_count); $pearson_den = sqrt(($sum_x_sq - pow($x_sum, 2) / $point_count) * ($sum_y_sq - pow($sum_y, 2) / $point_count)); $pearson_coefficient = $pearson_den == 0 ? 0 : $pearson_num / $pearson_den; $start_y = ($m * $this->i['left_start']) + $b; $end_y = ($m * $this->i['graph_left_end']) + $b; // TODO: hook into pearson_coefficient for figuring out if the line is good or not, for now if it goes out of bounds assume bad if($start_y > $this->i['graph_top_end'] || $start_y < $this->i['top_start'] || $end_y > $this->i['graph_top_end'] || $end_y < $this->i['top_start']) { continue; } $this->svg_dom->draw_svg_line($this->i['left_start'], $start_y, $this->i['graph_left_end'], $end_y, $paint_color, 2); } } protected function render_graph_identifiers() { return; $px_from_top_end = $this->i['graph_top_end'] + 5; if(!is_array($this->graph_identifiers)) { return; } $this->svg_dom->draw_svg_line($this->i['left_start'] + $this->i['identifier_width'], $this->i['graph_top_end'], $this->i['graph_left_end'], $this->i['graph_top_end'], self::$c['color']['notches'], 10, array('stroke-dasharray' => '1,' . ($this->i['identifier_width'] - 1))); foreach(array_keys($this->graph_identifiers) as $i) { if(is_array($this->graph_identifiers[$i])) { break; } if($this->i['display_select_identifiers'] && ($i % $this->i['display_select_identifiers']) != 0) { // $this->i['display_select_identifiers'] contains the value of how frequently to display identifiers continue; } $px_from_left = $this->i['left_start'] + ($this->i['identifier_width'] * ($i + 1)); if($this->i['identifier_size'] <= $this->i['min_identifier_size']) { $this->svg_dom->add_text_element($this->graph_identifiers[$i], array('x' => $px_from_left, 'y' => ($px_from_top_end + 2), 'font-size' => 9, 'fill' => self::$c['color']['headers'], 'text-anchor' => 'start', 'dominant-baseline' => 'middle', 'transform' => 'rotate(90 ' . $px_from_left . ' ' . ($px_from_top_end + 2) . ')')); } else { $this->svg_dom->add_text_element($this->graph_identifiers[$i], array('x' => $px_from_left, 'y' => ($px_from_top_end + 2), 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['headers'], 'text-anchor' => 'middle', 'dominant-baseline' => 'text-before-edge')); } } } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_MultiPassFailGraph.php0000644000175000017500000001644011727421404027037 0ustar michaelmichael. */ class pts_MultiPassFailGraph extends pts_Graph { public function __construct(&$result_object, &$result_file = null) { parent::__construct($result_object, $result_file); $this->i['hide_y_title'] = true; $this->i['graph_value_type'] = 'ABSTRACT'; $this->i['hide_graph_identifiers'] = true; } protected function render_graph_passfail() { $identifier_count = count($this->graph_identifiers); $vertical_border = 20; $horizontal_border = 14; $heading_height = 24; $graph_width = $this->i['graph_left_end'] - $this->i['left_start'] - ($horizontal_border * 2); $graph_height = $this->i['graph_top_end'] - $this->i['top_start'] - ($vertical_border * 2) - $heading_height; $line_height = floor($graph_height / $identifier_count); $pass_color = $this->get_paint_color('PASS'); $fail_color = $this->get_paint_color('FAIL'); $main_width = floor($graph_width * .24); $main_font_size = self::$c['size']['bars']; $main_greatest_length = pts_strings::find_longest_string($this->graph_identifiers); $width = $main_width - 8; $height = $line_height - 4; $main_font_size = $this->text_size_bounds($main_greatest_length, $main_font_size, 4, $width, $height); if(($new_size = $this->text_string_width($main_greatest_length, $main_font_size)) < ($main_width - 12)) { $main_width = $new_size + 10; } $identifiers_total_width = $graph_width - $main_width - 2; $headings = pts_strings::comma_explode($this->graph_y_title); $identifiers_width = floor($identifiers_total_width / count($headings)); $headings_font_size = self::$c['size']['bars']; while(($this->text_string_width(pts_strings::find_longest_string($headings), $headings_font_size) > ($identifiers_width - 2)) || $this->text_string_height($this->i['graph_max_value'], $headings_font_size) > ($line_height - 4)) { $headings_font_size -= 0.5; } for($j = 0; $j < count($this->graph_data[0]); $j++) { $results = array_reverse(pts_strings::comma_explode($this->graph_data[0][$j])); $line_ttf_height = $this->text_string_height('AZ@![]()@|_', self::$c['size']['bars']); for($i = 0; $i < count($headings) && $i < count($results); $i++) { $paint_color = $results[$i] == 'PASS' ? $pass_color : $fail_color; $this_bottom_end = $this->i['top_start'] + $vertical_border + (($j + 1) * $line_height) + $heading_height + 1; if($this_bottom_end >= $this->i['graph_top_end'] - $vertical_border) { $this_bottom_end = $this->i['graph_top_end'] - $vertical_border - 1; } else if($j == (count($this->graph_data[0]) - 1) && $this_bottom_end < $this->i['graph_top_end'] - $vertical_border) { $this_bottom_end = $this->i['graph_top_end'] - $vertical_border - 1; } $x = $this->i['graph_left_end'] - $horizontal_border - ($i * $identifiers_width); $y = $this->i['top_start'] + $vertical_border + ($j * $line_height) + $heading_height; $this->svg_dom->add_element('rect', array('x' => ($x - $identifiers_width), 'y' => $y, 'width' => $identifiers_width, 'height' => ($this_bottom_end - $y), 'fill' => $paint_color, 'stroke' => self::$c['color']['border'], 'stroke-width' => 1)); $x = $this->i['graph_left_end'] - $horizontal_border - ($i * $identifiers_width) - ($identifiers_width * 0.5); $y = $this->i['top_start'] + $vertical_border + ($j * $line_height) + $heading_height + ($line_height / 2) - ($line_ttf_height / 2); $this->svg_dom->add_text_element($results[$i], array('x' => $x, 'y' => $y, 'font-size' => self::$c['size']['bars'], 'fill' => self::$c['color']['body_text'], 'text-anchor' => 'middle', 'dominant-baseline' => 'text-before-edge')); } } $headings = array_reverse($headings); $line_ttf_height = $this->text_string_height('AZ@![]()@|_', $headings_font_size); for($i = 0; $i < count($headings); $i++) { $this->svg_dom->draw_svg_line($this->i['graph_left_end'] - $horizontal_border - (($i + 1) * $identifiers_width), $this->i['top_start'] + $vertical_border, $this->i['graph_left_end'] - $horizontal_border - (($i + 1) * $identifiers_width), $this->i['graph_top_end'] - $vertical_border, self::$c['color']['body_light']); $x = $this->i['graph_left_end'] - $horizontal_border - ($i * $identifiers_width) - (0.5 * $identifiers_width); $y = $this->i['top_start'] + $vertical_border + ($heading_height / 2) - ($line_ttf_height / 2); $this->svg_dom->add_text_element($headings[$i], array('x' => $x, 'y' => $y, 'font-size' => $headings_font_size, 'fill' => self::$c['color']['headers'], 'text-anchor' => 'middle', 'dominant-baseline' => 'text-before-edge')); } $line_ttf_height = $this->text_string_height('AZ@![]()@|_', $main_font_size); for($i = 0; $i < count($this->graph_identifiers); $i++) { $this->svg_dom->draw_svg_line($this->i['left_start'] + $horizontal_border, $this->i['top_start'] + $vertical_border + ($i * $line_height) + $heading_height, $this->i['graph_left_end'] - $horizontal_border, $this->i['top_start'] + $vertical_border + ($i * $line_height) + $heading_height, self::$c['color']['body_light']); $x = $this->i['left_start'] + $horizontal_border + $main_width; $y = $this->i['top_start'] + $vertical_border + ($i * $line_height) + $heading_height + ($line_height / 2) - 2; $this->svg_dom->add_text_element($this->graph_identifiers[$i], array('x' => $x, 'y' => $y, 'font-size' => $main_font_size, 'fill' => self::$c['color']['headers'], 'text-anchor' => 'end', 'dominant-baseline' => 'middle')); } $this->svg_dom->draw_svg_line($this->i['left_start'] + $horizontal_border, $this->i['top_start'] + $vertical_border, $this->i['graph_left_end'] - $horizontal_border, $this->i['top_start'] + $vertical_border, self::$c['color']['body_light']); $this->svg_dom->draw_svg_line($this->i['left_start'] + $horizontal_border, $this->i['top_start'] + $vertical_border, $this->i['left_start'] + $horizontal_border, $this->i['graph_top_end'] - $vertical_border, self::$c['color']['body_light']); $this->svg_dom->draw_svg_line($this->i['graph_left_end'] - $horizontal_border, $this->i['top_start'] + $vertical_border, $this->i['graph_left_end'] - $horizontal_border, $this->i['graph_top_end'] - $vertical_border, self::$c['color']['body_light']); $this->svg_dom->draw_svg_line($this->i['left_start'] + $horizontal_border, $this->i['graph_top_end'] - $vertical_border, $this->i['graph_left_end'] - $horizontal_border, $this->i['graph_top_end'] - $vertical_border, self::$c['color']['body_light']); } protected function render_graph_result() { $this->render_graph_passfail(); } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_PassFailGraph.php0000644000175000017500000000736511727420777026046 0ustar michaelmichael. */ class pts_PassFailGraph extends pts_Graph { public function __construct(&$result_object, &$result_file = null) { parent::__construct($result_object, $result_file); $this->i['graph_value_type'] = 'ABSTRACT'; $this->i['hide_graph_identifiers'] = true; $this->graph_data_title = array('PASSED', 'FAILED'); } protected function render_graph_passfail() { $identifier_count = count($this->graph_identifiers); $vertical_border = 18; $horizontal_border = 10; $spacing = 8; $columns = 1; $graph_width = $this->i['graph_left_end'] - $this->i['left_start'] - ($horizontal_border * 2); $graph_height = $this->i['graph_top_end'] - $this->i['top_start'] - ($vertical_border * 1.5); $font_size = self::$c['size']['bars'] * 1.5; $pass_color = $this->get_paint_color('PASS'); $fail_color = $this->get_paint_color('FAIL'); for($i = 2; $i <= sqrt($identifier_count); $i++) { if(intval($identifier_count / $i) == ($identifier_count / $i)) { $columns = $i; } } $identifiers_per_column = $identifier_count / $columns; $identifier_height = floor(($graph_height - (($identifiers_per_column - 1) * $spacing)) / $identifiers_per_column); $identifier_width = floor(($graph_width - (($columns - 1) * $spacing)) / $columns); $width = $identifier_width - 8; $height = $identifier_height - 4; $main_font_size = $this->text_size_bounds($this->i['graph_max_value'], $font_size, 4, $width, $height); for($c = 0; $c < $columns; $c++) { for($i = 0; $i < $identifiers_per_column; $i++) { $element_i = ($c * $identifiers_per_column) + $i; $this_identifier = $this->graph_identifiers[$element_i]; $this_value = $this->graph_data[0][$element_i]; $this_x_start = $this->i['left_start'] + $horizontal_border + ($c * ($identifier_width + $spacing)); $this_x_end = $this->i['left_start'] + $horizontal_border + ($c * ($identifier_width + $spacing)) + $identifier_width; $this_y_start = $this->i['top_start'] + $vertical_border + ($i * ($identifier_height + $spacing)); $this_y_end = $this->i['top_start'] + $vertical_border + ($i * ($identifier_height + $spacing)) + $identifier_height; $paint_color = $this_value == 'PASS' ? $pass_color : $fail_color; $this->svg_dom->add_element('rect', array('x' => $this_x_start, 'y' => $this_y_start, 'width' => $identifier_width, 'height' => $identifier_height, 'fill' => $paint_color, 'stroke' => self::$c['color']['body_light'], 'stroke-width' => 1)); $x = $this_x_start + (($this_x_end - $this_x_start) / 2); $y = $this_y_start + (($this_y_end - $this_y_start) / 2); $this->svg_dom->add_text_element($this_identifier, array('x' => $x, 'y' => $y, 'font-size' => $font_size, 'fill' => self::$c['color']['body_text'], 'text-anchor' => 'middle', 'dominant-baseline' => 'middle')); } } } protected function render_graph_result() { $this->render_graph_passfail(); } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_FilledLineGraph.php0000644000175000017500000001204611713775522026337 0ustar michaelmichael. */ class pts_FilledLineGraph extends pts_LineGraph { protected function renderGraphLines() { $identifiers_empty = count($this->graph_identifiers) == 0; $point_count = count($this->graph_data[0]); $varying_lengths = false; $prev_values = array(); $prev_poly_points = array(); foreach($this->graph_data as &$graph_r) { if(count($graph_r) != $point_count) { $varying_lengths = true; break; } } foreach(array_keys($this->graph_data) as $z => $i_o) { $paint_color = $this->get_paint_color((isset($this->graph_data_title[$i_o]) ? $this->graph_data_title[$i_o] : null)); $point_counter = count($this->graph_data[$i_o]); $regression_plots = array(); $poly_points = array(); for($i = 0; $i < $point_counter; $i++) { $value = $this->graph_data[$i_o][$i]; if(isset($prev_values[$i])) { $value += $prev_values[$i]; } $prev_values[$i] = $value; $identifier = isset($this->graph_identifiers[$i]) ? $this->graph_identifiers[$i] : null; $data_string = isset($this->graph_data_title[$i_o]) ? $this->graph_data_title[$i_o] . ($identifier ? ' @ ' . $identifier : null) . ': ' . $value : null; $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 + 1))); /* if(($i == ($point_counter - 1)) && $value == 0) { break; } */ if($px_from_left > $this->i['graph_left_end']) { //$px_from_left = $this->i['graph_left_end'] - 1; break; } if($value_plot_top >= $this->i['graph_top_end']) { $value_plot_top = $this->i['graph_top_end'] - 1; } if($identifiers_empty && $i == 0) { array_push($poly_points, array($this->i['left_start'] + 1, ($this->i['graph_top_end'] + 1))); array_push($poly_points, array($this->i['left_start'] + 1, $value_plot_top, $data_string)); } else if($identifiers_empty && $i == ($point_counter - 1)) { array_push($poly_points, array($px_from_left, $value_plot_top, $data_string)); if($varying_lengths && ($point_counter * 1.1) < $point_count) { // This plotting ended prematurely array_push($poly_points, array($px_from_left, $this->i['graph_top_end'] - 1, null)); } else if($value > 0) { array_push($poly_points, array($this->i['graph_left_end'] - 1, $value_plot_top, null)); } } else { if($i == 0) { array_push($poly_points, array($px_from_left, ($this->i['graph_top_end'] + 1))); } array_push($poly_points, array($px_from_left, $value_plot_top, $data_string)); } //array_push($poly_tips, array($value, $this->graph_identifiers[$i])); } switch($z) { case 0: array_push($poly_points, array($px_from_left, ($this->i['graph_top_end'] + 1))); array_push($poly_points, $poly_points[0]); break; case 1: $prev_poly_points = array_slice($prev_poly_points, 0, -2); default: array_shift($poly_points); array_unshift($poly_points, $prev_poly_points[1]); foreach(array_reverse($prev_poly_points) as $p) { array_push($poly_points, $p); } break; } $svg_poly = array(); foreach($poly_points as $point_pair) { array_push($svg_poly, implode(',', $point_pair)); } $this->svg_dom->add_element('polygon', array('points' => implode(' ', $svg_poly), 'fill' => $paint_color, 'stroke' => self::$c['color']['main_headers'], 'stroke-width' => 1)); $prev_poly_points = array_merge($poly_points, $prev_poly_points); } } protected function maximum_graph_value() { $values = array(); foreach(array_keys($this->graph_data) as $z => $i_o) { for($i = 0; $i < count($this->graph_data[$i_o]); $i++) { if(!isset($values[$i])) { $values[$i] = 0; } $values[$i] += $this->graph_data[$i_o][$i]; } } $maximum = max($values); $maximum = (floor(round($maximum * 1.285) / $this->i['mark_count']) + 1) * $this->i['mark_count']; $maximum = round(ceil($maximum / $this->i['mark_count']), (0 - strlen($maximum) + 2)) * $this->i['mark_count']; return $maximum; } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_ResultFileTable.php0000644000175000017500000003055411704717247026400 0ustar michaelmichael. */ class pts_ResultFileTable extends pts_Table { public $flagged_results = array(); public function __construct(&$result_file, $system_id_keys = null, $result_object_index = -1, $extra_attributes = null) { list($rows, $columns, $table_data) = self::result_file_to_result_table($result_file, $system_id_keys, $result_object_index, $this->flagged_results, $extra_attributes); parent::__construct($rows, $columns, $table_data, $result_file); $this->result_object_index = $result_object_index; if($result_object_index == -1) { $this->graph_title = $result_file->get_title(); } else { $result_object = $result_file->get_result_objects($result_object_index); $this->graph_title = $result_object[0]->test_profile->get_title(); array_push($this->graph_sub_titles, $result_object[0]->get_arguments_description()); } // where to start the table values $this->longest_row_identifier = null; $longest_row_title_length = 0; foreach($this->rows as $result_test) { if(($len = strlen($result_test)) > $longest_row_title_length) { $this->longest_row_identifier = $result_test; $longest_row_title_length = $len; } } } public static function result_file_to_result_table(&$result_file, &$system_id_keys = null, &$result_object_index = -1, &$flag_delta_results = false, $extra_attributes = null) { $result_table = array(); $result_tests = array(); $result_counter = 0; foreach($result_file->get_system_identifiers() as $sys_identifier) { $result_table[$sys_identifier] = null; } foreach($result_file->get_result_objects($result_object_index) as $ri => $result_object) { if($extra_attributes != null) { if(isset($extra_attributes['reverse_result_buffer'])) { $result_object->test_result_buffer->buffer_values_reverse(); } if(isset($extra_attributes['normalize_result_buffer'])) { if(isset($extra_attributes['highlight_graph_values']) && is_array($extra_attributes['highlight_graph_values']) && count($extra_attributes['highlight_graph_values']) == 1) { $normalize_against = $extra_attributes['highlight_graph_values'][0]; } else { $normalize_against = false; } $result_object->normalize_buffer_values($normalize_against); } } if($result_object_index != -1) { if(is_array($result_object_index)) { $result_tests[$result_counter] = new pts_graph_ir_value($result_object->get_arguments_description()); } else { $result_tests[$result_counter] = new pts_graph_ir_value('Results'); } } else { $result_tests[$result_counter] = new pts_graph_ir_value($result_object->test_profile->get_title()); $result_tests[$result_counter]->set_attribute('title', $result_object->get_arguments_description()); if($result_object->test_profile->get_identifier() != null) { $result_tests[$result_counter]->set_attribute('href', 'http://openbenchmarking.org/test/' . $result_object->test_profile->get_identifier()); } } if($result_object->test_profile->get_identifier() == null) { if($result_object->test_profile->get_display_format() == 'BAR_GRAPH') { $result_tests[$result_counter]->set_attribute('alert', true); foreach($result_object->test_result_buffer->get_buffer_items() as $index => $buffer_item) { $identifier = $buffer_item->get_result_identifier(); $value = $buffer_item->get_result_value(); $result_table[$identifier][$result_counter] = new pts_graph_ir_value($value, array('alert' => true)); } $result_counter++; } continue; } switch($result_object->test_profile->get_display_format()) { case 'BAR_GRAPH': $best_value = 0; $worst_value = 0; if(!defined('PHOROMATIC_TRACKER') && count($result_object->test_result_buffer->get_values()) > 1) { switch($result_object->test_profile->get_result_proportion()) { case 'HIB': $best_value = max($result_object->test_result_buffer->get_values()); $worst_value = min($result_object->test_result_buffer->get_values()); break; case 'LIB': $best_value = min($result_object->test_result_buffer->get_values()); $worst_value = max($result_object->test_result_buffer->get_values()); break; } } $prev_value = 0; $prev_identifier = null; $prev_identifier_0 = null; $values_in_buffer = $result_object->test_result_buffer->get_values(); sort($values_in_buffer); $min_value_in_buffer = $values_in_buffer[0]; if($min_value_in_buffer == 0) { // Go through the values until something not 0, otherwise down in the code will be a divide by zero for($i = 1; $i < count($values_in_buffer) && $min_value_in_buffer == 0; $i++) { $min_value_in_buffer = $values_in_buffer[$i]; } } $max_value_in_buffer = $values_in_buffer[(count($values_in_buffer) - 1)]; foreach($result_object->test_result_buffer->get_buffer_items() as $index => $buffer_item) { $identifier = $buffer_item->get_result_identifier(); $value = $buffer_item->get_result_value(); $raw_values = pts_strings::colon_explode($buffer_item->get_result_raw()); $percent_std = pts_math::set_precision(pts_math::percent_standard_deviation($raw_values), 2); $std_error = pts_math::set_precision(pts_math::standard_error($raw_values), 2); $delta = 0; if(defined('PHOROMATIC_TRACKER')) { $identifier_r = pts_strings::colon_explode($identifier); if($identifier_r[0] == $prev_identifier_0 && $prev_value != 0) { $delta = pts_math::set_precision(abs(1 - ($value / $prev_value)), 4); if($delta > 0.02 && $delta > pts_math::standard_deviation($raw_values)) { switch($result_object->test_profile->get_result_proportion()) { case 'HIB': if($value < $prev_value) { $delta = 0 - $delta; } break; case 'LIB': if($value > $prev_value) { $delta = 0 - $delta; } break; } } else { $delta = 0; } } $prev_identifier_0 = $identifier_r[0]; $highlight = false; $alert = false; } else { if($result_file->is_multi_way_comparison()) { // TODO: make it work better for highlighting multiple winners in multi-way comparisons $highlight = false; $alert = false; // TODO: get this working right if(false && $index % 2 == 1 && $prev_value != 0) { switch($result_object->test_profile->get_result_proportion()) { case 'HIB': if($value > $prev_value) { $highlight = true; } else { $result_table[$prev_identifier][$result_counter]->set_attribute('highlight', true); $result_table[$prev_identifier][$result_counter]->set_attribute('delta', -1); } break; case 'LIB': if($value < $prev_value) { $highlight = true; } else { $result_table[$prev_identifier][$result_counter]->set_attribute('highlight', true); $result_table[$prev_identifier][$result_counter]->set_attribute('delta', -1); } break; } } } else { $alert = $worst_value == $value; $highlight = $best_value == $value; } if($min_value_in_buffer != $max_value_in_buffer) { switch($result_object->test_profile->get_result_proportion()) { case 'HIB': $delta = pts_math::set_precision($value / $min_value_in_buffer, 2); break; case 'LIB': $delta = pts_math::set_precision(1 - ($value / $max_value_in_buffer) + 1, 2); break; } } } $attributes = array( 'std_percent' => $percent_std, 'std_error' => $std_error, 'delta' => $delta, 'highlight' => $highlight, 'alert' => $alert ); if($delta > $percent_std && $flag_delta_results !== false) { $flag_delta_results[$ri] = $delta; } $result_table[$identifier][$result_counter] = new pts_graph_ir_value($value, $attributes); $prev_identifier = $identifier; $prev_value = $value; } break; case 'LINE_GRAPH': case 'FILLED_LINE_GRAPH': $result_tests[$result_counter] = new pts_graph_ir_value($result_object->test_profile->get_title() . ' (Avg)'); foreach($result_object->test_result_buffer->get_buffer_items() as $index => $buffer_item) { $identifier = $buffer_item->get_result_identifier(); $values = pts_strings::comma_explode($buffer_item->get_result_value()); $avg_value = pts_math::set_precision(array_sum($values) / count($values), 2); $result_table[$identifier][$result_counter] = new pts_graph_ir_value($avg_value); } break; } $result_counter++; } if($result_counter == 1) { // This should provide some additional information under normal modes $has_written_std = false; $has_written_diff = false; $has_written_error = false; foreach($result_table as $identifier => $info) { if(!isset($info[($result_counter - 1)])) { continue; } $std_percent = $info[($result_counter - 1)]->get_attribute('std_percent'); $std_error = $info[($result_counter - 1)]->get_attribute('std_error'); $delta = $info[($result_counter - 1)]->get_attribute('delta'); if($delta != 0) { array_push($result_table[$identifier], new pts_graph_ir_value($delta . 'x')); $has_written_diff = true; } if($std_error != 0) { array_push($result_table[$identifier], new pts_graph_ir_value($std_error)); $has_written_error = true; } if($std_percent != 0) { array_push($result_table[$identifier], new pts_graph_ir_value($std_percent . '%')); $has_written_std = true; } } if($has_written_diff) { array_push($result_tests, new pts_graph_ir_value('Difference')); } if($has_written_error) { array_push($result_tests, new pts_graph_ir_value('Standard Error')); } if($has_written_std) { array_push($result_tests, new pts_graph_ir_value('Standard Deviation')); } } if(defined('PHOROMATIC_TRACKER')) { // Resort the results by SYSTEM, then date $systems_table = array(); $sorted_table = array(); foreach($result_table as $system_identifier => &$identifier_table) { $identifier = pts_strings::colon_explode($system_identifier); if(!isset($systems_table[$identifier[0]])) { $systems_table[$identifier[0]] = array(); } $systems_table[$identifier[0]][$system_identifier] = $identifier_table; } $result_table = array(); $result_systems = array(); foreach($systems_table as &$group) { foreach($group as $identifier => $table) { $result_table[$identifier] = $table; $identifier = pts_strings::colon_explode($identifier); $show_id = isset($identifier[1]) ? $identifier[1] : $identifier[0];/* if($system_id_keys != null && ($s = array_search($identifier[0], $system_id_keys)) !== false) { $system_id = $s; } else { $system_id = null; }*/ array_push($result_systems, $show_id); } } } else { $result_systems = array(); foreach(array_keys($result_table) as $id) { array_push($result_systems, $id); } } return array($result_tests, $result_systems, $result_table); } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_BlockDiagramGraph.php0000644000175000017500000000555011732715712026645 0ustar michaelmichael. */ class pts_BlockDiagramGraph extends pts_Graph { public function __construct(&$result_file) { $result_object = null; parent::__construct($result_object, $result_file); $this->i['graph_width'] = 1000; $this->i['graph_height'] = 600; return true; } protected function render_graph_heading($with_version = true) { return; } public function renderGraph() { $this->i['top_heading_height'] = max(self::$c['size']['headers'] + 22 + self::$c['size']['key'], 48); $this->i['top_start'] = $this->i['top_heading_height'] + 50; $this->update_graph_dimensions($this->i['graph_width'], $this->i['graph_height'] + $this->i['top_start'], true); // Do the actual work $this->render_graph_init(); $this->graph_key_height(); $this->render_graph_key(); $this->render_graph_heading(); $data = array(1, 2, 3, 6, 7, 8, 9, 10); $center_block_x = round($this->i['graph_width'] / 2); $center_block_y = round($this->i['graph_height'] / 2); for($ring = 0, $blocks_per_ring = (count($data) <= 5 ? 5 : 4), $ring_size = ceil(count($data) / $blocks_per_ring); $ring < $ring_size; $ring++) { $depth = ($ring + 1) * (min($center_block_x, $center_block_y) / ($ring_size + 0.25)); for($i = ($ring * $blocks_per_ring), $i_size = $i + $blocks_per_ring; $i < $i_size; $i++) { $this_degree = (360 / $blocks_per_ring) * (($i % $blocks_per_ring) + ($ring / $ring_size)); $this_block_x = round($center_block_x + (cos(deg2rad($this_degree)) * $depth)); $this_block_y = round($center_block_y - (sin(deg2rad($this_degree)) * $depth)); $this->svg_dom->draw_svg_line($center_block_x, $center_block_y, $this_block_x, $this_block_y, self::$c['color']['notches'], 2); $this->svg_dom->add_element('rect', array('x' => ($this_block_x - 20), 'y' => ($this_block_y - 20), 'width' => 40, 'height' => 40, 'fill' => self::$c['color']['alert'])); } } $this->svg_dom->add_element('rect', array('x' => ($center_block_x - 50), 'y' => ($center_block_y - 50), 'width' => 100, 'height' => 100, 'fill' => self::$c['color']['alert'])); } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_HorizontalBarGraph.php0000644000175000017500000001677012173542713027111 0ustar michaelmichael. */ class pts_HorizontalBarGraph extends pts_Graph { public function __construct(&$result_object, &$result_file = null) { parent::__construct($result_object, $result_file); $this->i['iveland_view'] = true; $this->i['graph_orientation'] = 'HORIZONTAL'; $this->i['identifier_height'] = -1; } protected function render_graph_pre_init() { // Do some common work to this object $identifier_count = count($this->graph_identifiers); $this->i['identifier_height'] = floor(($this->i['graph_top_end'] - $this->i['top_start']) / $identifier_count); } protected function render_graph_identifiers() { $px_from_top_end = $this->i['graph_top_end'] + 5; $this->svg_dom->draw_svg_line($this->i['left_start'], $this->i['top_start'] + $this->i['identifier_height'], $this->i['left_start'], $this->i['graph_top_end'] - ($this->i['graph_height'] % $this->i['identifier_height']), self::$c['color']['notches'], 10, array('stroke-dasharray' => 1 . ',' . ($this->i['identifier_height'] - 1))); $multi_way = $this->is_multi_way_comparison && count($this->graph_data) > 1; $middle_of_vert = $this->i['top_start'] + ($multi_way ? 5 : 0) - ($this->i['identifier_height'] * 0.5) - 2; foreach(array_keys($this->graph_identifiers) as $i) { $middle_of_vert += $this->i['identifier_height']; if($multi_way) { foreach(explode(' - ', $this->graph_identifiers[$i]) as $i => $identifier_line) { $x = 8; $this->svg_dom->add_text_element($identifier_line, array('x' => $x, 'y' => $middle_of_vert, 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['headers'], 'text-anchor' => 'middle', 'transform' => 'rotate(90 ' . $x . ' ' . $middle_of_vert . ')')); } } else { $this->svg_dom->add_text_element($this->graph_identifiers[$i], array('x' => ($this->i['left_start'] - 5), 'y' => $middle_of_vert, 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['headers'], 'text-anchor' => 'end')); } } } protected function render_graph_bars() { $bar_count = count($this->graph_data); $separator_height = ($a = (6 - (floor($bar_count / 2) * 2))) > 0 ? $a : 0; $multi_way = $this->is_multi_way_comparison && count($this->graph_data) > 1; $bar_height = floor(($this->i['identifier_height'] - ($multi_way ? 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; 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 = $this->graph_data[$i_o][$i]; $graph_size = max(0, round(($value / $this->i['graph_max_value']) * ($this->i['graph_left_end'] - $this->i['left_start']))); $value_end_right = max($this->i['left_start'] + $graph_size, 1); $px_bound_top = $this->i['top_start'] + ($multi_way ? 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) + ($this->i['identifier_size'] - 4); $title_tooltip = $this->graph_identifiers[$i] . ': ' . $value; $std_error = -1; if(isset($this->graph_data_raw[$i_o][$i])) { $std_error = pts_strings::colon_explode($this->graph_data_raw[$i_o][$i]); switch(count($std_error)) { case 0: $std_error = -1; break; case 1: $std_error = 0; break; default: $std_error = pts_math::standard_error($std_error); break; } } $this->svg_dom->add_element('rect', array('x' => $this->i['left_start'], 'y' => $px_bound_top, 'width' => $graph_size, 'height' => $bar_height, 'fill' => (in_array($this->graph_identifiers[$i], $this->value_highlights) ? self::$c['color']['highlight'] : $paint_color), 'stroke' => self::$c['color']['body_light'], 'stroke-width' => 1, 'xlink:title' => $title_tooltip)); if($std_error != -1 && $value != null) { $std_error_height = 8; if($std_error > 0 && is_numeric($std_error)) { $std_error_rel_size = round(($std_error / $this->i['graph_max_value']) * ($this->i['graph_left_end'] - $this->i['left_start'])); if($std_error_rel_size > 4) { $this->svg_dom->draw_svg_line(($value_end_right - $std_error_rel_size), $px_bound_top, ($value_end_right - $std_error_rel_size), $px_bound_top + $std_error_height, self::$c['color']['notches'], 1); $this->svg_dom->draw_svg_line(($value_end_right + $std_error_rel_size), $px_bound_top, ($value_end_right + $std_error_rel_size), $px_bound_top + $std_error_height, self::$c['color']['notches'], 1); $this->svg_dom->draw_svg_line(($value_end_right - $std_error_rel_size), $px_bound_top, ($value_end_right + $std_error_rel_size), $px_bound_top, self::$c['color']['notches'], 1); } } $bar_offset_34 = $middle_of_bar + ($multi_way ? 0 : ($bar_height / 5) + 1); $this->svg_dom->add_text_element('SE +/- ' . pts_math::set_precision($std_error, 2), array('x' => ($this->i['left_start'] - 5), 'y' => $bar_offset_34, 'font-size' => ($this->i['identifier_size'] - 2), 'fill' => self::$c['color']['text'], 'text-anchor' => 'end')); } if(($this->text_string_width($value, $this->i['identifier_size']) + 2) < $graph_size) { if(isset($this->d['identifier_notes'][$this->graph_identifiers[$i]])) { $note_size = self::$c['size']['key'] - 2; $this->svg_dom->add_text_element($this->d['identifier_notes'][$this->graph_identifiers[$i]], array('x' => ($this->i['left_start'] + 4), 'y' => ($px_bound_top + self::$c['size']['key']), 'font-size' => $note_size, 'fill' => self::$c['color']['body_text'], 'text-anchor' => 'start')); } $this->svg_dom->add_text_element($value, array('x' => ($value_end_right - 5), 'y' => $middle_of_bar, 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['body_text'], 'text-anchor' => 'end')); } else if($value > 0) { // Write it in front of the result $this->svg_dom->add_text_element($value, array('x' => ($value_end_right + 6), 'y' => $middle_of_bar, 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['text'], 'text-anchor' => 'start')); } } } // 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); } protected function render_graph_result() { $this->render_graph_bars(); } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_HeatMapBarGraph.php0000644000175000017500000002441311732657623026277 0ustar michaelmichael. */ class pts_HeatMapBarGraph extends pts_Graph { protected $bars; protected $last_updated; protected $keys; public function __construct($keys = array(), $last_updated = null) { $this->bars = array(); $this->keys = $keys; $this->last_updated = $last_updated; } public function set_keys($keys = array()) { $this->keys = $keys; } public function add_result_bar($min_value, $max_value, $bin_size, $sections, $lines, $test_data, $results = array()) { if($min_value == $max_value) { return false; } array_push($this->bars, array( 'min_value' => $min_value, 'max_value' => $max_value, 'bin_size' => $bin_size, 'sections' => $sections, 'draw_lines' => $lines, 'test_data' => $test_data, 'results' => $results )); } public function get_count() { return count($this->bars); } protected static function compare_bars_by_hardware_subsystem($a, $b) { return $a['test_data']['h'] == $b['test_data']['h'] ? strcmp($a['test_data']['t'], $b['test_data']['t']) : strcmp($a['test_data']['h'], $b['test_data']['h']); } public function sort_results_by_hardware_subsystem() { usort($this->bars, array('self', 'compare_bars_by_hardware_subsystem')); } public function generate_display() { $bar_width = 580; $bar_height = 38; $heading_per_bar = 16; $title_bar_height = 35; $footer_bar_height = 14; $category_offsets = 0; $category_heights = 30; $categories = array(); $border = 3; foreach($this->bars as &$bar) { if($bar['test_data']['h'] != null && !in_array($bar['test_data']['h'], $categories)) { array_push($categories, $bar['test_data']['h']); } } if(empty($this->keys)) { foreach($this->bars as &$bar_index) { foreach(array_keys($bar_index['results']) as $result_identifier) { if(!in_array($result_identifier, $this->keys)) { array_push($this->keys, $result_identifier); } } } } if(!empty($this->keys)) { list($longest_key_width, $key_line_height) = pts_svg_dom::estimate_text_dimensions(pts_strings::find_longest_string($this->keys), '', 10, true); $key_line_height += 18; $keys_per_line = max(floor($bar_width / max(1, $longest_key_width + 12)), 1); $title_key_offset = ceil(count($this->keys) / $keys_per_line) * $key_line_height; } else { $title_key_offset = 0; } $this->i['graph_width'] = $bar_width + ($border * 2); $this->i['graph_height'] = ($bar_height + $heading_per_bar + $border) * count($this->bars) + $border + (count($categories) * $category_heights) + $title_bar_height + $title_key_offset + $footer_bar_height; $this->svg_dom = new pts_svg_dom(ceil($this->i['graph_width']), ceil($this->i['graph_height'])); $text_color = '#e12128'; $alt_text_color = '#646464'; // Setup $start_x = $border; $end_x = $start_x + $bar_width; // Title bar $this->svg_dom->add_element('image', array('xlink:href' => pts_svg_dom::embed_png_image(PTS_CORE_STATIC_PATH . 'images/ob-fulltext-183x32.png'), 'x' => ($end_x - 190), 'y' => 10, 'width' => 183, 'height' => 32)); if(!empty($this->keys)) { $color_cache = array('e12128', '065695', '007400'); for($i = 0, $c = count($this->keys); $i < $c; $i++) { $component_x = $border + ($i % $keys_per_line) * ($longest_key_width + 10); $component_y = (floor($i / $keys_per_line) * $key_line_height) + $title_bar_height + 3; $key_color = self::color_cache('opc', $this->keys[$i], $color_cache); //$key_color = self::color_gradient('e12128', '065695', ($i / $c)); $key_colors[$this->keys[$i]] = $key_color; $this->svg_dom->add_element('rect', array('x' => ($component_x + 1), 'y' => $component_y, 'width' => 10, 'height' => 10, 'fill' => $key_color, 'stroke' => self::$c['color']['border'], 'stroke-width' => 1)); $this->svg_dom->add_text_element($this->keys[$i], array('x' => ($component_x + 15), 'y' => ($component_y + 5), 'font-size' => 10, 'fill' => $key_color, 'text-anchor' => 'start')); } } $previous_category = null; foreach($this->bars as $i => &$hmap) { $upper_y = ($i * ($bar_height + $border + $heading_per_bar)) + $border + $title_bar_height + $title_key_offset + $category_offsets + $heading_per_bar; if($hmap['test_data']['h'] != null && $hmap['test_data']['h'] != $previous_category) { $this->svg_dom->add_text_element($hmap['test_data']['h'] . ' Tests', array('x' => ($start_x + ($bar_width / 2)), 'y' => $upper_y, 'font-size' => 16, 'fill' => $text_color, 'text-anchor' => 'middle')); $category_offsets += $category_heights; $upper_y += $category_heights; } $previous_category = $hmap['test_data']['h']; $lower_y = $upper_y + $bar_height; $value_size = $bar_width / ($hmap['max_value'] - $hmap['min_value']); $prev_color = '#ffffff'; $last_plot_x = $start_x; $this->svg_dom->add_text_element($hmap['test_data']['t'], array('x' => $start_x, 'y' => $upper_y, 'font-size' => 12, 'fill' => $text_color, 'text-anchor' => 'start')); $this->svg_dom->add_text_element($hmap['test_data']['a'], array('x' => $end_x, 'y' => $upper_y, 'font-size' => 10, 'fill' => $alt_text_color, 'text-anchor' => 'end')); if($hmap['test_data']['p'] == 'LIB') { // Invert results $new_sections = array(); foreach($hmap['sections'] as $next_section => $next_section_value) { $new_sections[($hmap['max_value'] - $next_section)] = $next_section_value; } ksort($new_sections); $hmap['sections'] = $new_sections; foreach($hmap['draw_lines'] as &$value) { $value = $hmap['max_value'] - $value; } foreach($hmap['results'] as &$value) { $value = $hmap['max_value'] - $value; } sort($hmap['draw_lines']); $hmap['max_value'] -= $hmap['min_value']; $hmap['min_value'] = 0; } $prev_section = $hmap['min_value']; $max_section_value = max($hmap['sections']); /* for($i = $hmap['min_value']; $i <= $hmap['max_size'] && $hmap['bin_size'] > 0; $i += $hmap['bin_size']) { } */ $color_weight = 0.61 - (0 / $max_section_value * 0.5); $background_color = self::color_gradient('#FFFFFF', '#000000', $color_weight); $this->svg_dom->add_element('rect', array('x' => $start_x, 'y' => $upper_y, 'width' => $bar_width, 'height' => $bar_height, 'fill' => $background_color)); foreach($hmap['sections'] as $next_section => $next_section_value) { $color_weight = 0.61 - ($next_section_value / $max_section_value * 0.5); $color = self::color_gradient('#FFFFFF', '#000000', $color_weight); if($next_section > $hmap['min_value']) { $next_section = $next_section > $hmap['max_value'] ? $hmap['max_value'] : $next_section; $plot_x = floor($last_plot_x + (($next_section - $prev_section) * $value_size)); $plot_x = $plot_x > $end_x ? $end_x : $plot_x; if($prev_color != $color || ($color != $background_color)) { // don't uselessly paint background color, it's already painted $this->svg_dom->draw_rectangle_gradient($last_plot_x, $upper_y, abs($plot_x - $last_plot_x), $bar_height, $prev_color, $color); } $last_plot_x = floor($plot_x - 0.6); $prev_section = $next_section; if($next_section > $hmap['max_value']) { break; } } $prev_color = $color; } /* if($prev_color != $background_color && $plot_x < $end_x) { $plot_x = $last_plot_x + $next_section + $hmap['bin_size']; $plot_x = $plot_x > $end_x ? $end_x : $plot_x; $this->svg_dom->draw_rectangle_gradient($last_plot_x, $upper_y, ceil($plot_x - $last_plot_x), $bar_height, $prev_color, $background_color); } if($last_plot_x < $end_x) { // Fill in the blank $this->svg_dom->add_element('rect', array('x' => $last_plot_x, 'y' => $upper_y, 'width' => ($end_x - $last_plot_x), 'height' => $bar_height, 'fill' => $prev_color)); } */ foreach($hmap['draw_lines'] as $line_value) { $line_x = $start_x + ($line_value - $hmap['min_value']) * $value_size; $this->svg_dom->draw_svg_line($line_x, $upper_y, $line_x, $lower_y, self::$c['color']['border'], 1); } foreach($hmap['results'] as $identifier => $value) { if(!isset($key_colors[$identifier])) { continue; } $line_x = $start_x + ($value - $hmap['min_value']) * $value_size; if(false && ($start_x + 10) < $line_x && $line_x < ($end_x - 10)) { $this->svg_dom->draw_svg_line($line_x, ($lower_y - 10), $line_x, ($lower_y - 1), $key_colors[$identifier], 1); $this->svg_dom->draw_svg_line($line_x, ($lower_y + 10), $line_x, ($lower_y + 1), $key_colors[$identifier], 1); } $this->svg_dom->draw_svg_line($line_x, $upper_y, $line_x, $lower_y, $key_colors[$identifier], 1); } $this->svg_dom->add_element('rect', array('x' => $start_x, 'y' => $upper_y, 'width' => $bar_width, 'height' => $bar_height, 'fill' => 'none', 'stroke' => self::$c['color']['border'], 'stroke-width' => 1)); } // Footer $this->draw_arrow($start_x + 8, $lower_y + 8, $start_x + 1, $lower_y + 8, $alt_text_color, self::$c['color']['border'], 1); $this->svg_dom->add_text_element('Percentile Rank' . ($this->last_updated != null ? '; Data As Of ' . pts_strings::time_stamp_to_string($this->last_updated, 'j F Y') . ' For Trailing 200 Days' : null), array('x' => $start_x + 13, 'y' => $lower_y + 8, 'font-size' => 7, 'fill' => $alt_text_color, 'text-anchor' => 'start', 'dominant-baseline' => 'middle')); $this->svg_dom->add_text_element('OpenBenchmarking.org Performance Classification', array('x' => $end_x, 'y' => $lower_y + 8, 'font-size' => 7, 'fill' => $alt_text_color, 'text-anchor' => 'end', 'dominant-baseline' => 'middle')); return $this->svg_dom; } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_ImageComparisonGraph.php0000644000175000017500000000736111715771022027402 0ustar michaelmichael. */ class pts_ImageComparisonGraph extends pts_Graph { public function __construct(&$result_object, &$result_file = null) { parent::__construct($result_object, $result_file); $this->i['graph_value_type'] = 'ABSTRACT'; $this->i['hide_graph_identifiers'] = true; $this->graph_data_title = array('PASSED', 'FAILED'); } protected function render_graph_pre_init() { if(!function_exists('imagecreatefromstring')) { echo PHP_EOL . 'Currently you must have PHP-GD installed to utilize this feature.' . PHP_EOL; return false; } // Do some common work to this object $draw_count = count($this->graph_identifiers); $img_first = imagecreatefromstring(base64_decode($this->graph_data[0][0])); $img_width = imagesx($img_first); $img_height = imagesy($img_first); // Assume if the images are being rendered together they are same width and height $this->i['graph_height'] = 72 + ($draw_count * ($img_height + 22)); // 110 at top plus 20 px between images $this->i['graph_width'] = $this->i['graph_width'] < ($img_width + 20) ? $img_width + 20 : $this->i['graph_width']; $this->update_graph_dimensions($this->i['graph_width'], $this->i['graph_height']); } public function renderGraph() { if(!function_exists('imagecreatefromstring')) { echo PHP_EOL . 'Currently you must have PHP-GD installed to utilize this feature.' . PHP_EOL; return false; } $this->render_graph_pre_init(); $this->render_graph_init(); $this->render_graph_heading(false); $img_first = imagecreatefromstring(base64_decode($this->graph_data[0][0])); $img_width = imagesx($img_first); $img_height = imagesy($img_first); unset($img_first); $draw_count = count($this->graph_identifiers); for($i_o = 0; $i_o < $draw_count; $i_o++) { $from_left = ($this->i['graph_width'] / 2) - ($img_width / 2); $from_top = 60 + ($i_o * ($img_height + 22)); $this->svg_dom->add_element('rect', array('x' => ($from_left - 1), 'y' => ($from_top - 1), 'width' => ($img_width + 2), 'height' => ($img_height + 2), 'fill' => self::$c['color']['body_light'])); $this->svg_dom->add_element('image', array('xlink:href' => 'data:image/png;base64,' . $this->graph_data[0][$i_o], 'x' => $from_left, 'y' => $from_top, 'width' => $img_width, 'height' => $img_height)); $this->svg_dom->add_text_element($this->graph_identifiers[$i_o], array('x' => round($this->i['graph_width'] / 2), 'y' => ($from_top + $img_height + 3), 'font-size' => self::$c['size']['bars'], 'fill' => self::$c['color']['main_headers'], 'text-anchor' => 'middle', 'dominant-baseline' => 'text-before-edge')); } if(!empty(self::$c['text']['watermark'])) { $this->svg_dom->add_text_element(self::$c['text']['watermark'], array('x' => (round($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')); } } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_RadarOverviewGraph.php0000644000175000017500000002651711777346264027127 0ustar michaelmichael. */ class pts_RadarOverviewGraph extends pts_Graph { public $skip_graph = false; private $result_objects = array(); private $result_file = null; public static function cmp_result_object_sort($a, $b) { $a = $a->test_profile->get_test_hardware_type() . $a->test_profile->get_result_scale_formatted() . $a->test_profile->get_test_software_type() . $a->test_profile->get_identifier(true) . $a->get_arguments_description(); $b = $b->test_profile->get_test_hardware_type() . $b->test_profile->get_result_scale_formatted() . $b->test_profile->get_test_software_type() . $b->test_profile->get_identifier(true) . $b->get_arguments_description(); return strcmp($a, $b); } public function __construct(&$result_file) { $result_object = null; parent::__construct($result_object, $result_file); // System Identifiers $system_identifiers = $result_file->get_system_identifiers(); if($result_file->is_multi_way_comparison() || count($result_file->get_test_titles()) < 3 || count($system_identifiers) < 3) { // Multi way comparisons currently render the overview graph as blank // If there aren't more than 3 tests then don't render // If there aren't 3 or more systems then don't render $this->skip_graph = true; return; } $result_objects = $result_file->get_result_objects(); usort($result_objects, array('pts_RadarOverviewGraph', 'cmp_result_object_sort')); foreach($result_objects as &$r) { if(count($r->test_result_buffer->get_buffer_items()) != count($system_identifiers)) { continue; } if($r->normalize_buffer_values() == false) { continue; } $r_multiple = max($r->test_result_buffer->get_values()); if($r_multiple > 10 || $r_multiple < 1.02) { continue; } $this->i['graph_max_value'] = max($this->i['graph_max_value'], $r_multiple); $r->test_result_buffer->sort_buffer_values(false); array_push($this->result_objects, $r); } if(count($this->result_objects) < 3) { // No point in generating this if there aren't many valid tests $this->skip_graph = true; return; } $this->i['identifier_size'] = 6.5; $this->i['graph_height'] = $this->i['graph_width']; $this->i['left_start'] = 35; $this->graph_title = $result_file->get_title(); $this->graph_data_title = $system_identifiers; $this->i['iveland_view'] = true; $this->result_file = &$result_file; return true; } public function doSkipGraph() { return $this->skip_graph; } protected function render_graph_heading($with_version = true) { $this->svg_dom->add_element('rect', array('x' => 0, 'y' => 0, 'width' => $this->i['graph_width'], 'height' => $this->i['top_heading_height'], 'fill' => self::$c['color']['main_headers'])); $this->svg_dom->add_element('image', array('xlink:href' => pts_svg_dom::embed_png_image(PTS_CORE_STATIC_PATH . 'images/pts-77x40-white.png'), 'x' => 10, 'y' => round($this->i['top_heading_height'] / 40 + 1), 'width' => 77, 'height' => 40)); $this->svg_dom->add_text_element($this->graph_title, array('x' => 100, 'y' => (4 + self::$c['size']['headers']), 'font-size' => self::$c['size']['headers'], 'fill' => self::$c['color']['background'], 'text-anchor' => 'start')); $this->svg_dom->add_text_element($this->i['graph_version'], array('x' => 100, 'y' => (self::$c['size']['headers'] + 16), 'font-size' => self::$c['size']['key'], 'fill' => self::$c['color']['background'], 'text-anchor' => 'start', 'href' => 'http://www.phoronix-test-suite.com/')); } public function renderGraph() { $this->i['top_heading_height'] = max(self::$c['size']['headers'] + 22 + self::$c['size']['key'], 48); $this->i['top_start'] = $this->i['top_heading_height'] + 50; $this->update_graph_dimensions($this->i['graph_width'], $this->i['graph_height'] + $this->i['top_start'], true); // Do the actual work $this->render_graph_init(); $this->graph_key_height(); $this->render_graph_key(); $this->render_graph_heading(); $work_area = $this->i['graph_left_end'] - $this->i['left_start']; $unit_size = floor($work_area / ($this->i['graph_max_value'] * 1.05)); for($i = $this->i['graph_max_value']; $i >= 0.99; $i -= (($this->i['graph_max_value'] - 1) / $this->i['mark_count'])) { $num = pts_math::set_precision(round($i, 1), 1); $length = round($unit_size * $num); $this->svg_dom->draw_svg_arc($this->i['left_start'], $this->i['top_start'], $length, 10, 0.25, array('fill' => self::$c['color']['background'], 'stroke' => self::$c['color']['body_light'], 'stroke-width' => 1, 'stroke-dasharray' => '10,20')); $this->svg_dom->add_text_element($num, array('x' => ($this->i['left_start'] + $length), 'y' => ($this->i['top_start'] - self::$c['size']['tick_mark'] + 2), 'font-size' => self::$c['size']['tick_mark'], 'fill' => self::$c['color']['notches'], 'text-anchor' => 'middle')); $this->svg_dom->draw_svg_line($this->i['left_start'] + $length, $this->i['top_start'] - 6, $this->i['left_start'] + $length, $this->i['top_start'], self::$c['color']['notches'], 1); $this->svg_dom->add_text_element($num, array('x' => ($this->i['left_start'] - 8), 'y' => ($this->i['top_start'] + $length), 'font-size' => self::$c['size']['tick_mark'], 'fill' => self::$c['color']['notches'], 'text-anchor' => 'end', 'dominant-baseline' => 'middle')); $this->svg_dom->draw_svg_line($this->i['left_start'] - 6, $this->i['top_start'] + $length, $this->i['left_start'], $this->i['top_start'] + $length, self::$c['color']['notches'], 1); } $this->svg_dom->draw_svg_line($this->i['left_start'], $this->i['top_start'], $this->i['graph_left_end'], $this->i['top_start'], self::$c['color']['notches'], 1); $this->svg_dom->draw_svg_line($this->i['left_start'], $this->i['top_start'], $this->i['left_start'], $this->i['graph_top_end'], self::$c['color']['notches'], 1); $this->svg_dom->draw_svg_line($this->i['graph_left_end'], $this->i['graph_top_end'], $this->i['graph_left_end'], $this->i['top_start'], self::$c['color']['notches'], 1); $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); for($i = 1, $result_object_count = count($this->result_objects); $i < $result_object_count; $i++) { for($c = 0, $c_count = $this->result_objects[$i]->test_result_buffer->get_count(); $c < $c_count; $c++) { $pre_rad = deg2rad(360 - ((($i - 1) / $result_object_count) * 90)); $pre_result = $this->result_objects[($i - 1)]->test_result_buffer->get_buffer_item($c)->get_result_value(); $result = $this->result_objects[$i]->test_result_buffer->get_buffer_item($c)->get_result_value(); if(($result_object_count - 1) == $i && 90 % $result_object_count != 0) { $rad = deg2rad(270); } else { $rad = deg2rad(360 - (($i / $result_object_count) * 90)); } $result_identifier = $this->result_objects[$i]->test_result_buffer->get_buffer_item($c)->get_result_identifier(); $pre_size = $unit_size * $pre_result; $size = $unit_size * $result; $tooltip = $this->result_objects[$i]->test_profile->get_title() . ' - ' . $this->result_objects[$i]->test_result_buffer->get_buffer_item($c)->get_result_identifier() . ' - ' . $this->result_objects[$i]->test_result_buffer->get_buffer_item($c)->get_result_value() . 'x Faster Than ' . $this->result_objects[$i]->test_result_buffer->get_buffer_item(($c_count - 1))->get_result_identifier(); $points = array( array($this->i['left_start'], $this->i['top_start']), array(round($this->i['left_start'] + cos($pre_rad) * $pre_size), round($this->i['top_start'] + abs(sin($pre_rad)) * $pre_size)), array(round($this->i['left_start'] + cos($rad) * $pre_size), round($this->i['top_start'] + abs(sin($rad)) * $pre_size)) ); $svg_poly = array(); foreach($points as $point_pair) { array_push($svg_poly, implode(',', $point_pair)); } $this->svg_dom->add_element('polygon', array('points' => implode(' ', $svg_poly), 'fill' => $this->get_paint_color($result_identifier), 'stroke' => self::$c['color']['text'], 'stroke-width' => 2, 'xlink:title' => $tooltip)); } } $this->svg_dom->draw_svg_arc($this->i['left_start'], $this->i['top_start'], round($unit_size), 10, 0.25, array('fill' => self::$c['color']['background'], 'stroke' => self::$c['color']['notches'], 'stroke-width' => 1)); $last_hardware_type = $this->result_objects[0]->test_profile->get_test_hardware_type(); $hw_types = array(); $last_hardware_type_i = 0; for($i = 0, $result_object_count = count($this->result_objects); $i < $result_object_count; $i++) { $hardware_type = $this->result_objects[$i]->test_profile->get_test_hardware_type(); if($hardware_type != $last_hardware_type || $i == ($result_object_count - 1)) { if($i != ($result_object_count - 1)) { $rad = deg2rad(360 - (($i / $result_object_count) * 90)); $cos_unit = cos($rad) * $unit_size; $sin_unit = abs(sin($rad)) * $unit_size; $this->svg_dom->draw_svg_line( round($this->i['left_start'] + $cos_unit), round($this->i['top_start'] + $sin_unit), round($this->i['left_start'] + $cos_unit * $this->i['graph_max_value']), round($this->i['top_start'] + $sin_unit * $this->i['graph_max_value']), self::$c['color']['alert'], 1); } $rad = deg2rad(360 - ((((($i - $last_hardware_type_i) / 2) + $last_hardware_type_i) / $result_object_count) * 90)); $cos_unit = $this->i['left_start'] + cos($rad) * $unit_size * 0.9; $sin_unit = $this->i['top_start'] + abs(sin($rad)) * $unit_size * 0.9; $this->svg_dom->add_text_element($last_hardware_type, array('x' => $cos_unit, 'y' => $sin_unit, 'font-size' => self::$c['size']['bars'], 'fill' => self::$c['color']['alert'], 'text-anchor' => 'end', 'dominant-baseline' => 'middle')); array_push($hw_types, $last_hardware_type); $last_hardware_type = $hardware_type; $last_hardware_type_i = $i; } } $hw = $this->result_file->get_system_hardware(); $sw = $this->result_file->get_system_software(); $shw = array(); foreach($this->graph_data_title as $i => $title) { $merged = pts_result_file_analyzer::system_component_string_to_array($hw[$i] . ', ' . $sw[$i], $hw_types); if(!empty($merged)) { $shw[$title] = $merged; } } $i = 1; foreach($shw as $key => $line) { $this->svg_dom->add_text_element(implode('; ', $line), array('x' => ($this->i['graph_left_end'] - 4), 'y' => ($this->i['graph_top_end'] - ($i * self::$c['size']['key'])), 'font-size' => self::$c['size']['key'], 'fill' => $this->get_paint_color($key), 'text-anchor' => 'end', 'dominant-baseline' => 'middle')); $i++; } } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_Table.php0000644000175000017500000004531311776424541024401 0ustar michaelmichael. */ class pts_Table extends pts_Graph { protected $rows; protected $rendered_rows; protected $columns; protected $table_data; protected $longest_column_identifier; protected $longest_row_identifier; protected $is_multi_way = false; protected $result_object_index = -1; protected $column_heading_vertical = true; public function __construct($rows, $columns, $table_data, &$result_file) { parent::__construct(); if($result_file instanceof pts_result_file) { $this->is_multi_way = $result_file->is_multi_way_comparison(); } if($this->is_multi_way) { foreach($columns as &$c_str) { // in multi-way comparisons this will be reported above, so don't need to report it in the column header as it kills space if(($c = strpos($c_str, ':')) !== false) { $c_str = substr($c_str, $c + 1); } } } $this->rows = $rows; $this->columns = $columns; $this->table_data = $table_data; // Do some calculations $this->longest_column_identifier = pts_strings::find_longest_string($this->columns); $this->longest_row_identifier = pts_strings::find_longest_string($this->rows); $this->i['graph_max_value'] = $this->find_longest_string_in_table_data($this->table_data); foreach($this->columns as &$column) { if(($column instanceof pts_graph_ir_value) == false) { $column = new pts_graph_ir_value($column); } } } protected function find_longest_string_in_table_data(&$table_data) { $longest_string = null; $longest_string_length = 0; foreach($table_data as &$column) { if($column == null) { continue; } foreach($column as &$row) { if($row instanceof pts_graph_ir_value) { $value = $row->get_value(); if(($spans_col = $row->get_attribute('spans_col')) > 1) { // Since the txt will be spread over multiple columns, it doesn't need to all fit into one $value = substr($value, 0, ceil(strlen($value) / $spans_col)); } } else { $value = $row; } if(isset($value[$longest_string_length])) { $longest_string = $value; $longest_string_length = strlen($value); } } } return $longest_string; } public function renderChart($save_as = null) { $this->render_graph_start(); $this->render_graph_finish(); return $this->svg_dom->output($save_as); } public function render_graph_start() { // Needs to be at least 86px wide for the PTS logo $this->i['left_start'] = ceil(max(86, ($this->text_string_width($this->longest_row_identifier, $this->i['identifier_size']) * 1.1) + 12)); if($this->column_heading_vertical) { $top_identifier_height = round($this->text_string_width($this->longest_column_identifier, $this->i['identifier_size']) * 1.1) + 12; $table_identifier_width = $this->text_string_height($this->longest_column_identifier, $this->i['identifier_size']); } else { $top_identifier_height = $this->text_string_height($this->longest_column_identifier, $this->i['identifier_size']) + 8; $table_identifier_width = round($this->text_string_width($this->longest_column_identifier, $this->i['identifier_size']) * 1.1) + 8; } // Needs to be at least 46px tall for the PTS logo $top_identifier_height = max($top_identifier_height, 48); if(defined('PHOROMATIC_TRACKER') || $this->is_multi_way) { $extra_heading_height = round($this->text_string_height($this->longest_column_identifier, self::$c['size']['headers']) * 1.25); $top_identifier_height += 6 + $extra_heading_height; } $this->i['top_heading_height'] = 8; if($this->graph_title != null) { $this->i['top_heading_height'] += round(self::$c['size']['headers'] + (count($this->graph_sub_titles) * (self::$c['size']['sub_headers'] + 4))); } $table_max_value_width = ceil($this->text_string_width($this->i['graph_max_value'], $this->i['identifier_size']) * 1.02) + 2; $table_item_width = max($table_max_value_width, $table_identifier_width) + 2; $table_width = max(($table_item_width * count($this->columns)), floor($this->text_string_width($this->graph_title, 12) / $table_item_width) * $table_item_width); //$table_width = $table_item_width * count($this->columns); $table_line_height = round($this->text_string_height($this->i['graph_max_value'], $this->i['identifier_size']) + 8); $table_line_height_half = round($table_line_height / 2); $table_height = $table_line_height * count($this->rows); $table_proper_height = $this->i['top_heading_height'] + $table_height + $top_identifier_height; $this->i['graph_width'] = $table_width + $this->i['left_start']; $this->i['graph_height'] = round($table_proper_height + $table_line_height); if(!empty($this->i['notes'])) { $this->i['graph_height'] += $this->note_display_height(); } // Do the actual work $this->render_graph_pre_init(); $this->render_graph_init(); $this->svg_dom->add_element('rect', array('x' => 1, 'y' => 1, 'width' => ($this->i['graph_width'] - 1), 'height' => ($this->i['graph_height'] - 1), 'fill' => self::$c['color']['background'], 'stroke' => self::$c['color']['border'], 'stroke-width' => 1)); // Start drawing if($this->i['left_start'] >= 170 && $top_identifier_height >= 90) { $this->svg_dom->add_element('image', array('http_link' => 'http://www.phoronix-test-suite.com/', 'xlink:href' => pts_svg_dom::embed_png_image(PTS_CORE_STATIC_PATH . 'images/pts-160x83.png'), 'x' => round($this->i['left_start'] / 2 - 80), 'y' => round(($top_identifier_height / 2 - 41.5) + $this->i['top_heading_height']), 'width' => 160, 'height' => 83)); } else { $this->svg_dom->add_element('image', array('http_link' => 'http://www.phoronix-test-suite.com/', 'xlink:href' => pts_svg_dom::embed_png_image(PTS_CORE_STATIC_PATH . 'images/pts-80x42.png'), 'x' => round($this->i['left_start'] / 2 - 40), 'y' => round($top_identifier_height / 2 - 21 + $this->i['top_heading_height']), 'width' => 80, 'height' => 42)); } // Draw the vertical table lines $v = round((($top_identifier_height + $table_height) / 2) + $this->i['top_heading_height']); $table_columns_end = $this->i['left_start'] + ($table_item_width * count($this->columns)); $this->svg_dom->draw_svg_line($this->i['left_start'], $v, $table_columns_end, $v, self::$c['color']['body'], $table_height + $top_identifier_height, array('stroke-dasharray' => $table_item_width . ',' . $table_item_width)); if($table_columns_end < $this->i['graph_width']) { $this->svg_dom->add_element('rect', array('x' => $table_columns_end, 'y' => $this->i['top_heading_height'], 'width' => ($this->i['graph_width'] - $table_columns_end), 'height' => ($table_height + $top_identifier_height), 'fill' => self::$c['color']['body_light'])); } // Background horizontal $this->svg_dom->draw_svg_line(round($table_columns_end / 2), ($top_identifier_height + $this->i['top_heading_height']), round($table_columns_end / 2), $table_proper_height, self::$c['color']['body_light'], $table_columns_end, array('stroke-dasharray' => $table_line_height . ',' . $table_line_height)); // Draw the borders $this->svg_dom->draw_svg_line($this->i['left_start'], $v, $table_columns_end + ($table_columns_end < $this->i['graph_width'] ? $table_item_width : 0), $v, self::$c['color']['border'], $table_height + $top_identifier_height, array('stroke-dasharray' => '1,' . ($table_item_width - 1))); // Heading if($this->graph_title != null) { $this->svg_dom->add_element('rect', array('x' => 1, 'y' => 1, 'width' => ($this->i['graph_width'] - 2), 'height' => $this->i['top_heading_height'], 'fill' => self::$c['color']['main_headers'])); $this->svg_dom->add_text_element($this->graph_title, array('x' => 5, 'y' => (self::$c['size']['headers'] + 2), 'font-size' => self::$c['size']['headers'], 'fill' => self::$c['color']['background'], 'text-anchor' => 'start')); foreach($this->graph_sub_titles as $i => $sub_title) { $vertical_offset = 16 + self::$c['size']['headers'] + ($i * (self::$c['size']['sub_headers'])); $this->svg_dom->add_text_element($sub_title, array('x' => 5, 'y' => $vertical_offset, 'font-size' => self::$c['size']['sub_headers'], 'fill' => self::$c['color']['background'], 'text-anchor' => 'start')); } $this->svg_dom->draw_svg_line(1, $this->i['top_heading_height'], $this->i['graph_width'] - 1, $this->i['top_heading_height'], self::$c['color']['border'], 1); } // Write the rows $row = 1; foreach($this->rows as $i => $row_string) { if(($row_string instanceof pts_graph_ir_value) == false) { $row_string = new pts_graph_ir_value($row_string); } $text_color = $row_string->get_attribute('alert') ? self::$c['color']['alert'] : self::$c['color']['text']; $v = round($top_identifier_height + $this->i['top_heading_height'] + ($row * $table_line_height) - 4); $this->svg_dom->add_text_element($row_string, array('x' => ($this->i['left_start'] - 2), 'y' => $v, 'font-size' => $this->i['identifier_size'], 'fill' => $text_color, 'font-weight' => 'bold', 'text-anchor' => 'end', 'xlink:href' => $row_string->get_attribute('href'))); $row++; } // Write the identifiers if(defined('PHOROMATIC_TRACKER') || $this->is_multi_way) { $last_identifier = null; $last_changed_col = 0; $show_keys = array_keys($this->table_data); array_push($show_keys, 'Temp: Temp'); foreach($show_keys as $current_col => $system_identifier) { $identifier = pts_strings::colon_explode($system_identifier); if(isset($identifier[0]) && $identifier[0] != $last_identifier) { if($current_col == $last_changed_col) { $last_identifier = $identifier[0]; continue; } $paint_color = $this->get_paint_color($identifier[0]); if($this->i['top_heading_height'] > 0) { $extra_heading_height = $this->i['top_heading_height']; } $x = $this->i['left_start'] + 1 + ($last_changed_col * $table_item_width); $x_end = ($this->i['left_start'] + ($last_changed_col * $table_item_width)) + ($table_item_width * ($current_col - $last_changed_col)); $this->svg_dom->add_element('rect', array('x' => $x, 'y' => 0, 'width' => ($table_item_width * ($current_col - $last_changed_col)) - 2, 'height' => $extra_heading_height, 'fill' => $paint_color)); if($identifier[0] != 'Temp') { $this->svg_dom->draw_svg_line(($this->i['left_start'] + ($current_col * $table_item_width) + 1), 1, ($this->i['left_start'] + ($current_col * $table_item_width) + 1), $table_proper_height, $paint_color, 1); } //$x = $this->i['left_start'] + ($last_changed_col * $table_item_width) + ($this->i['left_start'] + ($current_col * $table_item_width) - $this->i['left_start'] + ($last_changed_col * $table_item_width)); $this->svg_dom->add_text_element($last_identifier, array('x' => round($x + (($x_end - $x) / 2)), 'y' => (self::$c['size']['axis_headers'] + 4), 'font-size' => self::$c['size']['axis_headers'], 'fill' => self::$c['color']['background'], 'font-weight' => 'bold', 'text-anchor' => 'middle')); $last_identifier = $identifier[0]; $last_changed_col = $current_col; } } } $table_identifier_offset = ($table_item_width / 2) + ($table_identifier_width / 2) - 1; foreach($this->columns as $i => $col_string) { if($this->column_heading_vertical) { $x = $this->i['left_start'] + ($i * $table_item_width) + $table_identifier_offset; $y = $this->i['top_heading_height'] + $top_identifier_height - 4; $this->svg_dom->add_text_element($col_string, array('x' => $x, 'y' => $y, 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['text'], 'font-weight' => 'bold', 'text-anchor' => 'end', 'transform' => 'rotate(90 ' . $x . ' ' . $y . ')')); } else { $x = $this->i['left_start'] + ($i * $table_item_width) + ($table_item_width / 2); $y = $this->i['top_heading_height'] + ($top_identifier_height / 2); $this->svg_dom->add_text_element($col_string, array('x' => $x, 'y' => $y, 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['text'], 'font-weight' => 'bold', 'text-anchor' => 'middle', 'dominant-baseline' => 'text-before-edge')); } } // Write the columns foreach($this->table_data as $index => &$table_values) { if(!is_array($table_values)) { // TODO: determine why sometimes $table_values is empty or not an array continue; } if($this->is_multi_way && ($c = strpos($index, ':')) !== false) { $index = substr($index, $c + 1); } $col = array_search(strval($index), $this->columns); if($col === false) { continue; } else { // unset this since it shouldn't be needed anymore and will then wipe out it from where multiple results have same name unset($this->columns[$col]); } foreach($table_values as $i => &$result_table_value) { $row = $i - 1; // if using $row, the alignment may be off sometimes $hover = array(); $text_color = self::$c['color']['text']; $bold = false; if($result_table_value == null) { continue; } if($result_table_value instanceof pts_graph_ir_value) { if(($t = $result_table_value->get_attribute('std_percent')) > 0) { array_push($hover, 'STD Dev: ' . $t . '%'); } if(($t = $result_table_value->get_attribute('std_error')) != 0) { array_push($hover, ' STD Error: ' . $t); } if(defined('PHOROMATIC_TRACKER') && ($t = $result_table_value->get_attribute('delta')) != 0) { $bold = true; $text_color = $t < 0 ? self::$c['color']['alert'] : self::$c['color']['headers']; array_push($hover, ' Change: ' . pts_math::set_precision(100 * $t, 2) . '%'); } else if($result_table_value->get_attribute('highlight') == true) { $text_color = self::$c['color']['highlight']; } else if($result_table_value->get_attribute('alert') == true) { $text_color = self::$c['color']['alert']; } $value = $result_table_value->get_value(); $spans_col = $result_table_value->get_attribute('spans_col'); } else { $value = $result_table_value; $spans_col = 1; } $left_bounds = $this->i['left_start'] + ($col * $table_item_width); $right_bounds = $this->i['left_start'] + (($col + max(1, $spans_col)) * $table_item_width); if($spans_col > 1) { if($col == 1) { $background_paint = $i % 2 == 1 ? self::$c['color']['background'] : self::$c['color']['body']; } else { $background_paint = $i % 2 == 0 ? self::$c['color']['body_light'] : self::$c['color']['body']; } $y = round($this->i['top_heading_height'] + $top_identifier_height + (($row + 1) * $table_line_height)); $this->svg_dom->add_element('rect', array('x' => $left_bounds, 'y' => $y + 1, 'width' => ($right_bounds - $left_bounds), 'height' => $table_line_height, 'fill' => $background_paint)); } $x = $left_bounds + (($right_bounds - $left_bounds) / 2); $this->svg_dom->add_text_element($result_table_value, array('x' => $x, 'y' => round($this->i['top_heading_height'] + $top_identifier_height + (($row + 2) * $table_line_height) - 3), 'font-size' => $this->i['identifier_size'], 'fill' => $text_color, 'text-anchor' => 'middle', 'xlink:title' => implode('; ', $hover), 'xlink:href' => $result_table_value->get_attribute('href'))); //$row++; } } //$this->svg_dom->draw_svg_line(($table_columns_end / 2), ($top_identifier_height + $this->i['top_heading_height']), round($table_columns_end / 2), $this->i['graph_height'], self::$c['color']['border'], $table_columns_end, array('stroke-dasharray' => '1,' . ($table_line_height - 1))); $this->svg_dom->draw_svg_line(round($table_columns_end / 2), ($top_identifier_height + $this->i['top_heading_height']), round($table_columns_end / 2), $table_proper_height, self::$c['color']['body_light'], $table_columns_end, array('stroke-dasharray' => 1 . ',' . ($table_line_height - 1))); // Bottom part $this->svg_dom->add_element('rect', array('x' => 0, 'y' => $table_proper_height, 'width' => $this->i['graph_width'], 'height' => ($this->i['graph_height'] - $table_proper_height), 'fill' => self::$c['color']['headers'])); $this->svg_dom->add_text_element(self::$c['text']['watermark'], array('x' => ($this->i['graph_width'] - 2), 'y' => ($this->i['graph_height'] - 3), 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['body_text'], 'text-anchor' => 'end', 'xlink:show' => 'new', 'xlink:href' => self::$c['text']['watermark_url'])); if(isset($this->d['link_alternate_view']) && $this->d['link_alternate_view']) { $this->svg_dom->add_text_element(0, array('x' => 6, 'y' => ($this->i['graph_height'] - 3), 'font-size' => 7, 'fill' => self::$c['color']['background'], 'text-anchor' => 'start', 'xlink:show' => 'new', 'xlink:href' => $this->d['link_alternate_view'], 'show' => 'replace', 'font-weight' => 'bold')); } if(!empty($this->i['notes'])) { $estimated_height = 0; $previous_section = null; foreach($this->i['notes'] as $i => $note_r) { if($note_r['section'] != null && $note_r['section'] !== $previous_section) { $estimated_height += 2; $this->svg_dom->add_textarea_element($note_r['section'] . ' Details', array('x' => 6, 'y' => ($table_proper_height + $table_line_height + $estimated_height), 'font-size' => (self::$c['size']['key'] - 1), 'fill' => self::$c['color']['background'], 'text-anchor' => 'start', 'xlink:title' => $note_r['hover-title'], 'style' => 'font-weight: bold'), $estimated_height); $estimated_height += 2; $previous_section = $note_r['section']; } $this->svg_dom->add_textarea_element('- ' . $note_r['note'], array('x' => 6, 'y' => ($table_proper_height + $table_line_height + $estimated_height), 'font-size' => (self::$c['size']['key'] - 1), 'fill' => self::$c['color']['background'], 'text-anchor' => 'start', 'xlink:title' => $note_r['hover-title']), $estimated_height); } } $this->rendered_rows = $row; } public function render_graph_finish() { if($this->rendered_rows == 0 && $this->result_object_index != -1 && !is_array($this->result_object_index)) { // No results were to be reported, so don't report the individualized graphs // destroy surface } } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_VerticalBarGraph.php0000644000175000017500000001465311732657775026546 0ustar michaelmichael. */ class pts_VerticalBarGraph extends pts_Graph { public function __construct(&$result_object, &$result_file = null) { parent::__construct($result_object, $result_file); if($result_file != null && $result_file instanceof pts_result_file) { $this->is_multi_way_comparison = $result_file->is_multi_way_comparison(); } $this->i['min_identifier_size'] = 6; $this->i['identifier_width'] = -1; } protected function render_graph_pre_init() { // Do some common work to this object $identifier_count = count($this->graph_identifiers); $this->i['identifier_width'] = floor(($this->i['graph_left_end'] - $this->i['left_start']) / $identifier_count); $longest_string = pts_strings::find_longest_string($this->graph_identifiers); $width = $this->i['identifier_width'] - 4; $this->i['identifier_size'] = $this->text_size_bounds($longest_string, $this->i['identifier_size'], $this->i['min_identifier_size'], $width); if($this->i['identifier_size'] <= $this->i['min_identifier_size']) { $this->update_graph_dimensions($this->i['graph_width'], $this->i['graph_height'] + $this->text_string_width($longest_string, 9)); } } protected function render_graph_identifiers() { $px_from_top_end = $this->i['graph_top_end'] + 5; $this->svg_dom->draw_svg_line($this->i['left_start'] + $this->i['identifier_width'], $this->i['graph_top_end'], $this->i['graph_left_end'] - ($this->i['graph_width'] % $this->i['identifier_width']), $this->i['graph_top_end'], self::$c['color']['notches'], 10, array('stroke-dasharray' => '1,' . ($this->i['identifier_width'] - 1))); foreach(array_keys($this->graph_identifiers) as $i) { $px_bound_left = $this->i['left_start'] + ($this->i['identifier_width'] * $i); $px_bound_right = $px_bound_left + $this->i['identifier_width']; if($i == (count($this->graph_identifiers) - 1) && $px_bound_right != $this->i['graph_left_end']) { $px_bound_right = $this->i['graph_left_end']; } if($this->i['identifier_size'] <= $this->i['min_identifier_size']) { $x = $px_bound_left + ceil($this->i['identifier_width'] / 2); $this->svg_dom->add_text_element($this->graph_identifiers[$i], array('x' => $x, 'y' => $px_from_top_end, 'font-size' => 9, 'fill' => self::$c['color']['headers'], 'text-anchor' => 'start', 'dominant-baseline' => 'middle', 'transform' => 'rotate(90 ' . $x . ' ' . $px_from_top_end . ')')); } else { $x = $px_bound_left + (($px_bound_right - $px_bound_left) * 0.5); $this->svg_dom->add_text_element($this->graph_identifiers[$i], array('x' => $x, 'y' => ($px_from_top_end + $this->i['identifier_size']), 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['headers'], 'text-anchor' => 'middle')); } } } 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); } protected function render_graph_result() { $this->render_graph_bars(); } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_graph_ir_value.php0000644000175000017500000000270311732663253026332 0ustar michaelmichael. */ class pts_graph_ir_value { private $value_string; private $attributes; public function __construct($value_string = 0, $attributes = array()) { $this->value_string = $value_string; $this->attributes = $attributes; } public function __toString() { return "$this->value_string"; } public function set_attribute($attribute, $value) { $this->attributes[$attribute] = $value; } public function get_attribute($attribute) { return isset($this->attributes[$attribute]) ? $this->attributes[$attribute] : null; } public function get_value() { return $this->value_string; } public function set_value_string($value) { $this->value_string = $value; } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_SideViewTable.php0000644000175000017500000002513511744551530026033 0ustar michaelmichael. */ class pts_SideViewTable extends pts_Graph { protected $rows; protected $columns; protected $table_data; protected $longest_column_identifier; protected $longest_row_identifier; protected $result_object_index = -1; protected $column_heading_vertical = true; public function __construct($rows, $columns, $table_data) { pts_Graph::__construct(); $this->rows = $rows; $this->columns = $columns; $this->table_data = $table_data; // Do some calculations $this->longest_column_identifier = pts_strings::find_longest_string($this->columns); $this->longest_row_identifier = pts_strings::find_longest_string($this->rows); foreach($this->columns as &$column) { if(($column instanceof pts_graph_ir_value) == false) { $column = new pts_graph_ir_value($column); } } $this->column_heading_vertical = false; } public function renderChart($save_as = null) { if(empty($this->rows) || empty($this->columns)) { return false; } $this->render_graph_start(); $this->render_graph_finish(); return $this->svg_dom->output($save_as); } public function render_graph_start() { // Needs to be at least 86px wide for the PTS logo $this->i['left_start'] = ceil(max(86, ($this->text_string_width($this->longest_row_identifier, $this->i['identifier_size']) * 1.09) + 8)); // Needs to be at least 46px tall for the PTS logo $top_identifier_height = max(($this->text_string_height($this->longest_column_identifier, $this->i['identifier_size']) + 8), 48); $this->i['top_heading_height'] = 1; if($this->graph_title != null) { $this->i['top_heading_height'] += round(self::$c['size']['headers'] + (count($this->graph_sub_titles) * (self::$c['size']['sub_headers'] + 4))); } $column_widths = array(); $row_heights = array_fill(0, count($this->rows), (ceil($this->i['identifier_size'] * 2.2))); foreach($this->columns as $i => $column) { $column_width = strlen($column); $column_index = -1; // See if any of the contained values in that column are longer than the column title itself foreach($this->table_data[$i] as $row => &$column_data) { if(isset($column_data[$column_width])) { $column = $column_data; $column_width = strlen($column_data); $column_index = $row; } if(strlen($column_data) > 64) { // If it's too long break it into multiple rows $row_heights[$row] = ceil($this->i['identifier_size'] * ceil(strlen($column_data) / 64)) + 18; $column = substr($column, 0, 64); } } $column_widths[$i] = ceil($this->text_string_width($column, $this->i['identifier_size']) * 1.02) + 14; } $table_width = $this->longest_row_identifier + array_sum($column_widths); $table_height = array_sum($row_heights); $table_proper_height = $this->i['top_heading_height'] + $table_height + $top_identifier_height; $this->i['graph_width'] = $table_width + $this->i['left_start'] + 1; $this->i['graph_height'] = round($table_proper_height + 16); if(!empty($this->i['notes'])) { $this->i['graph_height'] += $this->note_display_height(); } // Do the actual work $this->render_graph_pre_init(); $this->render_graph_init(); $this->svg_dom->add_element('rect', array('x' => 1, 'y' => 1, 'width' => ($this->i['graph_width'] - 1), 'height' => ($this->i['graph_height'] - 1), 'fill' => self::$c['color']['background'], 'stroke' => self::$c['color']['border'], 'stroke-width' => 1)); // Start drawing if($this->i['left_start'] >= 170 && $top_identifier_height >= 90) { $this->svg_dom->add_element('image', array('http_link' => 'http://www.phoronix-test-suite.com/', 'xlink:href' => pts_svg_dom::embed_png_image(PTS_CORE_STATIC_PATH . 'images/pts-160x83.png'), 'x' => round($this->i['left_start'] / 2 - 80), 'y' => round(($top_identifier_height / 2 - 41.5) + $this->i['top_heading_height']), 'width' => 160, 'height' => 83)); } else { $this->svg_dom->add_element('image', array('http_link' => 'http://www.phoronix-test-suite.com/', 'xlink:href' => pts_svg_dom::embed_png_image(PTS_CORE_STATIC_PATH . 'images/pts-80x42.png'), 'x' => round($this->i['left_start'] / 2 - 40), 'y' => round($top_identifier_height / 2 - 21 + $this->i['top_heading_height']), 'width' => 80, 'height' => 42)); } // Draw the vertical table lines $v = round((($top_identifier_height + $table_height) / 2) + $this->i['top_heading_height']); // Heading if($this->graph_title != null) { $this->svg_dom->add_element('rect', array('x' => 1, 'y' => 1, 'width' => ($this->i['graph_width'] - 2), 'height' => $this->i['top_heading_height'], 'fill' => self::$c['color']['main_headers'])); foreach($this->graph_sub_titles as $i => $sub_title) { $vertical_offset = 16 + self::$c['size']['headers'] + ($i * (self::$c['size']['sub_headers'])); $this->svg_dom->add_text_element($sub_title, array('x' => 5, 'y' => $vertical_offset, 'font-size' => self::$c['size']['sub_headers'], 'fill' => self::$c['color']['background'], 'text-anchor' => 'start')); } $this->svg_dom->draw_svg_line(1, $this->i['top_heading_height'], $this->i['graph_width'] - 1, $this->i['top_heading_height'], self::$c['color']['border'], 1); } // Write the rows $horizontal_offset = $top_identifier_height + $this->i['top_heading_height']; foreach($this->rows as $i => $row_string) { if($i % 2 == 0) { $this->svg_dom->add_element('rect', array('x' => 1, 'y' => $horizontal_offset, 'width' => $this->i['left_start'], 'height' => $row_heights[$i], 'fill' => self::$c['color']['body_light'], 'stroke' => self::$c['color']['border'], 'stroke-width' => 1)); } $this->svg_dom->add_text_element($row_string, array('x' => ($this->i['left_start'] - 4), 'y' => ($horizontal_offset + 16), 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['text'], 'font-weight' => 'bold', 'text-anchor' => 'end')); $horizontal_offset += $row_heights[$i]; } // Write the columns $y = $this->i['top_heading_height'] + ($top_identifier_height / 2) - 6; $column_width_offset = $this->i['left_start']; foreach($this->columns as $i => $col_string) { if($i % 2 == 0) { $this->svg_dom->add_element('rect', array('x' => $column_width_offset, 'y' => $this->i['top_heading_height'], 'width' => $column_widths[$i], 'height' => $top_identifier_height, 'fill' => self::$c['color']['body_light'], 'stroke' => self::$c['color']['border'], 'stroke-width' => 1)); } $this->svg_dom->add_text_element($col_string, array('x' => $column_width_offset + round($column_widths[$i] / 2) , 'y' => $y, 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['text'], 'font-weight' => 'bold', 'text-anchor' => 'middle', 'dominant-baseline' => 'text-before-edge')); $column_width_offset += $column_widths[$i]; } // Write the values $column_width_offset = $this->i['left_start']; $column_count = 0; foreach($this->table_data as $column => &$column_data) { $x = $column_width_offset + round($column_widths[$column_count] / 2); $row_count = 0; $row_offset = $top_identifier_height + $this->i['top_heading_height']; foreach($column_data as $row => &$value) { if(true || $column % 2 == 0 || $row % 2 != 1) { $this->svg_dom->add_element('rect', array('x' => $column_width_offset, 'y' => $row_offset, 'width' => $column_widths[$column_count], 'height' => $row_heights[$row], 'fill' => self::$c['color'][($row % 2 == 0 ? 'body' : 'body_light')], 'stroke' => self::$c['color']['border'], 'stroke-width' => 1)); } if(isset($value[64])) { // If it's a long string that needs to be broken to multiple linesd we need textarea to do automatic word wrapping $this->svg_dom->add_textarea_element($value, array('x' => $x, 'y' => ($row_offset + 16), 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['text'], 'text-anchor' => 'middle', 'width' => ($column_widths[$column_count] - 8))); } else { $this->svg_dom->add_text_element($value, array('x' => $x, 'y' => ($row_offset + 16), 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['text'], 'text-anchor' => 'middle')); } $row_count++; $row_offset += $row_heights[$row]; } $column_width_offset += $column_widths[$column_count]; $column_count++; } // Bottom part $this->svg_dom->add_element('rect', array('x' => 0, 'y' => $table_proper_height, 'width' => $this->i['graph_width'], 'height' => ($this->i['graph_height'] - $table_proper_height), 'fill' => self::$c['color']['headers'])); $this->svg_dom->add_text_element(self::$c['text']['watermark'], array('x' => ($this->i['graph_width'] - 2), 'y' => ($this->i['graph_height'] - 3), 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['body_text'], 'text-anchor' => 'end', 'xlink:show' => 'new', 'xlink:href' => self::$c['text']['watermark_url'])); if(!empty($this->i['notes'])) { $estimated_height = 0; $previous_section = null; foreach($this->i['notes'] as $i => $note_r) { if($note_r['section'] != null && $note_r['section'] !== $previous_section) { $estimated_height += 2; $this->svg_dom->add_textarea_element($note_r['section'] . ' Details', array('x' => 6, 'y' => ($table_proper_height + 14 + $estimated_height), 'font-size' => (self::$c['size']['key'] - 1), 'fill' => self::$c['color']['background'], 'text-anchor' => 'start', 'xlink:title' => $note_r['hover-title'], 'style' => 'font-weight: bold'), $estimated_height); $estimated_height += 2; $previous_section = $note_r['section']; } $this->svg_dom->add_textarea_element('- ' . $note_r['note'], array('x' => 6, 'y' => ($table_proper_height + 14 + $estimated_height), 'font-size' => (self::$c['size']['key'] - 1), 'fill' => self::$c['color']['background'], 'text-anchor' => 'start', 'xlink:title' => $note_r['hover-title']), $estimated_height); } } } public function render_graph_finish() { return true; } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_ResultFileCompactSystemsTable.php0000644000175000017500000002021111742304267031260 0ustar michaelmichael. */ class pts_ResultFileCompactSystemsTable extends pts_Graph { protected $components; protected $intent; public function __construct(&$result_file, $intent = false) { parent::__construct(); $this->intent = is_array($intent) ? $intent : array(array(), array()); $this->graph_title = $result_file->get_title(); $hw = $result_file->get_system_hardware(); $sw = $result_file->get_system_software(); $hw = pts_result_file_analyzer::system_component_string_to_array(array_shift($hw)); $sw = pts_result_file_analyzer::system_component_string_to_array(array_shift($sw)); $this->components = array_merge($hw, $sw); pts_render::report_system_notes_to_table($result_file, $this); } public function renderChart($file = null) { $this->render_graph_start(); $this->render_graph_finish(); return $this->svg_dom->output($file); } public function render_graph_start() { $this->i['top_heading_height'] = 22 + self::$c['size']['headers']; $longest_component = pts_strings::find_longest_string($this->components); $component_header_height = $this->text_string_height($longest_component, ($this->i['identifier_size'] + 3)) + 6; $this->i['graph_width'] = 10 + max( $this->text_string_width($this->graph_title, self::$c['size']['headers']) - (isset($this->graph_title[30]) ? 20 : 0), $this->text_string_width($longest_component, ($this->i['identifier_size'] + (isset($longest_component[29]) ? 1.8 : 2))) ); $intent_count = 0; $dupes = array(); if($this->intent[1] && is_array($this->intent[1])) { foreach($this->intent[1] as $x) { if(!in_array($x, $dupes)) { $intent_count += count($x); array_push($dupes, $x); } } $intent_count -= count($this->intent[0]); } unset($dupes); $bottom_footer = 50 + $this->note_display_height(); // needs to be at least 86 to make room for PTS logo $this->i['graph_height'] = $this->i['top_heading_height'] + ((count($this->components) + $intent_count) * $component_header_height) + $bottom_footer ; // Do the actual work $this->render_graph_pre_init(); $this->render_graph_init(); // Header $this->svg_dom->add_element('rect', array('x' => 2, 'y' => 1, 'width' => ($this->i['graph_width'] - 3), 'height' => ($this->i['top_heading_height'] - 1), 'fill' => self::$c['color']['main_headers'], 'stroke' => self::$c['color']['border'], 'stroke-width' => 1)); $this->svg_dom->add_text_element($this->graph_title, array('x' => ($this->i['graph_width'] / 2), 'y' => (2 + self::$c['size']['headers']), 'font-size' => self::$c['size']['headers'], 'fill' => self::$c['color']['background'], 'text-anchor' => 'middle')); $this->svg_dom->add_text_element(self::$c['text']['watermark'], array('x' => 4, 'y' => ($this->i['top_heading_height'] - 3), 'font-size' => 8, 'fill' => self::$c['color']['background'], 'text-anchor' => 'start', 'xlink:show' => 'new', 'xlink:href' => self::$c['text']['watermark_url'])); $this->svg_dom->add_text_element($this->i['graph_version'], array('x' => ($this->i['graph_width'] - 4), 'y' => ($this->i['top_heading_height'] - 3), 'font-size' => 8, 'fill' => self::$c['color']['background'], 'text-anchor' => 'end', 'xlink:show' => 'new', 'xlink:href' => 'http://www.phoronix-test-suite.com/')); // Body $offset = $this->i['top_heading_height']; $dash = false; foreach($this->components as $type => $component) { if(is_array($this->intent[0]) && ($key = array_search($type, $this->intent[0])) !== false) { $component = array(); foreach($this->intent[1] as $s) { if(isset($s[$key])) { array_push($component, $s[$key]); } } // Eliminate duplicates from printing $component = array_unique($component); $next_offset = $offset + ($component_header_height * count($component)); } else { $next_offset = $offset + $component_header_height; $component = array($component); } if($dash) { $this->svg_dom->add_element('rect', array('x' => 0, 'y' => $offset, 'width' => $this->i['graph_width'], 'height' => ($next_offset - $offset), 'fill' => self::$c['color']['body_light'])); } $this->svg_dom->draw_svg_line(0, $offset, $this->i['graph_width'], $offset, self::$c['color']['notches'], 1); if(isset($component[1])) { $this->svg_dom->add_element('rect', array('x' => 1, 'y' => ($offset + 1), 'width' => ($this->i['graph_width'] - 2), 'height' => ($next_offset - $offset - 1), 'fill' => 'none', 'stroke-width' => 1, 'stroke' => self::$c['color']['highlight'])); } $text = $type . (isset($component[1]) && substr($type, -1) != 'y' ? 's' : null); $this->svg_dom->add_text_element($text, array('x' => ($this->i['graph_width'] - 4), 'y' => ($offset + 9), 'font-size' => 7, 'fill' => self::$c['color']['text'], 'text-anchor' => 'end')); $offset += 2; foreach($component as $c) { $c = pts_result_file_analyzer::system_value_to_ir_value($c, $type); $this->svg_dom->add_text_element($c, array('x' => ($this->i['graph_width'] / 2), 'y' => ($offset + $component_header_height - 5), 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['text'], 'text-anchor' => 'middle', 'xlink:title' => $type . ': ' . $c, 'font-weight' => 'bold', 'xlink:href' => $c->get_attribute('href'))); $offset += $component_header_height; } $offset = $next_offset; $dash = !$dash; } // Footer $this->svg_dom->add_element('rect', array('x' => 1, 'y' => ($this->i['graph_height'] - $bottom_footer), 'width' => ($this->i['graph_width'] - 2), 'height' => $bottom_footer, 'fill' => self::$c['color']['main_headers'])); $this->svg_dom->add_element('image', array('http_link' => 'http://www.phoronix-test-suite.com/', 'xlink:href' => pts_svg_dom::embed_png_image(PTS_CORE_STATIC_PATH . 'images/pts-80x42-white.png'), 'x' => 10, 'y' => ($this->i['graph_height'] - 46), 'width' => 80, 'height' => 42)); if(defined('OPENBENCHMARKING_IDS')) { $back_width = $this->i['graph_width'] - 4; $this->svg_dom->add_text_element(OPENBENCHMARKING_TITLE, array('x' => $back_width, 'y' => ($this->i['graph_height'] - $bottom_footer + 12), 'font-size' => 8, 'fill' => self::$c['color']['background'], 'text-anchor' => 'end', 'font-weight' => 'bold', 'xlink:show' => 'new', 'xlink:href' => 'http://openbenchmarking.org/result/' . OPENBENCHMARKING_IDS)); $this->svg_dom->add_text_element('System Logs', array('x' => $back_width, 'y' => ($this->i['graph_height'] - 20), 'font-size' => 8, 'fill' => self::$c['color']['background'], 'text-anchor' => 'end', 'xlink:show' => 'new', 'xlink:href' => 'http://openbenchmarking.org/system/' . OPENBENCHMARKING_IDS)); $this->svg_dom->add_text_element('OPC Classification', array('x' => $back_width, 'y' => ($this->i['graph_height'] - 6), 'font-size' => 8, 'fill' => self::$c['color']['background'], 'text-anchor' => 'end', 'xlink:show' => 'new', 'xlink:href' => 'http://openbenchmarking.org/opc/' . OPENBENCHMARKING_IDS)); } if(!empty($this->i['notes'])) { $estimated_height = 0; foreach($this->i['notes'] as $i => $note_r) { $this->svg_dom->add_textarea_element('- ' . $note_r['note'], array('x' => 4, 'y' => ($this->i['graph_height'] - $bottom_footer + $estimated_height + 21), 'font-size' => self::$c['size']['key'], 'fill' => self::$c['color']['background'], 'text-anchor' => 'start', 'xlink:title' => $note_r['hover-title']), $estimated_height); } } } public function render_graph_finish() { } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_ResultFileSystemsTable.php0000644000175000017500000000373011742313304027750 0ustar michaelmichael. */ class pts_ResultFileSystemsTable extends pts_Table { public function __construct(&$result_file) { $columns = $result_file->get_system_identifiers(); $rows = array(); $table_data = array(); pts_result_file_analyzer::system_components_to_table($table_data, $columns, $rows, $result_file->get_system_hardware()); pts_result_file_analyzer::system_components_to_table($table_data, $columns, $rows, $result_file->get_system_software()); pts_result_file_analyzer::compact_result_table_data($table_data, $columns, true); // TODO: see if this true value works fine but if rendering starts messing up, disable it if(defined('OPENBENCHMARKING_IDS')) { foreach($columns as &$column) { $column = new pts_graph_ir_value($column); $column->set_attribute('href', 'http://openbenchmarking.org/system/' . OPENBENCHMARKING_IDS . '/' . $column); } } parent::__construct($rows, $columns, $table_data, $result_file); $this->i['identifier_size'] *= 0.8; $this->column_heading_vertical = false; $this->graph_title = $result_file->get_title(); pts_render::report_system_notes_to_table($result_file, $this); } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_OverviewGraph.php0000644000175000017500000001700611764132725026135 0ustar michaelmichael. */ class pts_OverviewGraph extends pts_Graph { protected $result_file; protected $system_identifiers; protected $test_titles; protected $graphs_per_row; protected $graph_item_width; protected $graph_row_height = 100; protected $graph_row_count; public $skip_graph = false; public function __construct($result_file) { $result_object = null; parent::__construct($result_object, $result_file); // System Identifiers if($result_file->is_multi_way_comparison()) { // Multi way comparisons currently render the overview graph as blank $this->skip_graph = true; return; } $this->system_identifiers = $result_file->get_system_identifiers(); if(count($this->system_identifiers) < 2) { // No point in generating this when there is only one identifier $this->skip_graph = true; return; } $result_objects = array(); foreach($result_file->get_result_objects() as $result_object) { if($result_object->test_profile->get_display_format() == 'BAR_GRAPH') { array_push($result_objects, $result_object); } } $result_object_count = count($result_objects); if($result_object_count < 3) { // No point in generating this if there aren't many tests $this->skip_graph = true; return; } $result_file->override_result_objects($result_objects); // Test Titles $this->i['identifier_size'] = 6.5; $this->i['graph_width'] = 1000; $titles = $result_file->get_test_titles(); list($longest_title_width, $longest_title_height) = pts_svg_dom::estimate_text_dimensions(pts_strings::find_longest_string($titles), $this->i['identifier_size']); $this->i['left_start'] += 20; $this->graphs_per_row = floor(($this->i['graph_width'] - $this->i['left_start'] - $this->i['left_end_right']) / ($longest_title_width + 2)); $this->graph_item_width = floor(($this->i['graph_width'] - $this->i['left_start'] - $this->i['left_end_right']) / $this->graphs_per_row); $this->graph_row_count = ceil($result_object_count / $this->graphs_per_row); $this->i['top_start'] += 14; $height = $this->i['top_start'] + ($this->graph_row_count * ($this->graph_row_height + 15)); $this->graph_title = $result_file->get_title(); $this->graph_y_title = null; $this->i['graph_proportion'] = 'HIB'; $this->i['show_background_lines'] = true; $this->update_graph_dimensions($this->i['graph_width'], $height, true); $this->result_file = $result_file; return true; } public function doSkipGraph() { return $this->skip_graph; } public function renderGraph() { $this->graph_data_title = &$this->system_identifiers; $this->i['mark_count'] = 6; $this->i['graph_max_value'] = 1.2; $l_height = 15; $this->i['key_line_height'] = $l_height; if(($key_count = count($this->graph_data_title)) > 8) { $this->update_graph_dimensions(-1, $this->i['graph_height'] + (floor(($key_count - 8) / 4) * 14), true); } // Do the actual work $this->render_graph_init(); $this->render_graph_key(); for($i = 0; $i < $this->graph_row_count; $i++) { $this->render_graph_base($this->i['left_start'], $this->i['top_start'] + ($i * ($this->graph_row_height + $l_height)), $this->i['graph_left_end'], $this->i['top_start'] + ($i * ($this->graph_row_height + $l_height)) + $this->graph_row_height); $this->render_graph_value_ticks($this->i['left_start'], $this->i['top_start'] + ($i * ($this->graph_row_height + $l_height)), $this->i['graph_left_end'], $this->i['top_start'] + ($i * ($this->graph_row_height + $l_height)) + $this->graph_row_height); } $row = 0; $col = 0; $bar_count = count($this->system_identifiers); $inter_width = $this->graph_item_width * 0.1; $bar_width = floor(($this->graph_item_width - ($inter_width * 2)) / $bar_count); $has_graphed_a_bar = false; foreach($this->result_file->get_result_objects() as $i => $result_object) { $top_start = $this->i['top_start'] + ($row * ($this->graph_row_height + $l_height)); $top_end = round($this->i['top_start'] + ($row * ($this->graph_row_height + $l_height)) + $this->graph_row_height); $px_bound_left = $this->i['left_start'] + ($this->graph_item_width * ($col % $this->graphs_per_row)); $px_bound_right = $px_bound_left + $this->graph_item_width; $this->svg_dom->add_text_element($result_object->test_profile->get_title(), array('x' => ($px_bound_left + ($this->graph_item_width * 0.5)), 'y' => ($top_end + 3), 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['headers'], 'text-anchor' => 'middle', 'dominant-baseline' => 'text-before-edge')); if($result_object->test_profile->get_display_format() == 'BAR_GRAPH') { $all_values = $result_object->test_result_buffer->get_values(); switch($result_object->test_profile->get_result_proportion()) { case 'HIB': $divide_value = max($all_values); break; case 'LIB': $divide_value = min($all_values); break; } foreach($result_object->test_result_buffer->get_buffer_items() as $x => $buffer_item) { $paint_color = $this->get_paint_color($buffer_item->get_result_identifier()); switch($result_object->test_profile->get_result_proportion()) { case 'HIB': $value = $buffer_item->get_result_value() / $divide_value; break; case 'LIB': $value = $divide_value / $buffer_item->get_result_value(); break; } $graph_size = round(($value / $this->i['graph_max_value']) * ($top_end - $top_start)); $value_plot_top = $top_end + 1 - $graph_size; $px_left = $px_bound_left + $inter_width + ($bar_width * $x); $px_right = $px_left + $bar_width; $this->svg_dom->add_element('rect', array('x' => $px_left, 'y' => $value_plot_top, 'width' => $bar_width, 'height' => ($top_end - $value_plot_top), 'fill' => $paint_color, 'stroke' => self::$c['color']['body_light'], 'stroke-width' => 1)); } $has_graphed_a_bar = true; } if(($i + 1) % $this->graphs_per_row == 0 && $i != 0) { $this->svg_dom->draw_svg_line($this->i['left_start'] + $this->graph_item_width, $top_end, $this->i['graph_left_end'] - ($this->i['graph_width'] % $this->graph_item_width), $top_end, self::$c['color']['notches'], 10, array('stroke-dasharray' => '1,' . ($this->graph_item_width - 1))); $this->svg_dom->draw_svg_line($this->i['left_start'], $top_end, $this->i['graph_left_end'], $top_end, self::$c['color']['notches'], 1); $row++; } $col++; } if($has_graphed_a_bar == false) { // Don't show an empty overview graph... $this->skip_graph = true; } //$this->render_graph_base($this->i['left_start'], $this->i['top_start'], $this->i['graph_left_end'], $this->i['graph_top_end']); $this->render_graph_heading(); //$this->render_graph_watermark(); } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_Graph.php0000644000175000017500000010377212200177113024376 0ustar michaelmichael. */ // TODO: performance optimizations... // OpenBenchmarking.org 1107247-LI-MESACOMMI48 is a good large data set test to render to look for speed differences // Other tests: // 1201120-BY-MESA80GAL31 // TODO: elimiante need for some of the pts_* classes called inside here, instead build them in or find other efficient ways of handling... // Setup main config values, should only be needed once since the configuration values should never be over-written within pts_Graph* pts_Graph::init_graph_config(); abstract class pts_Graph { // Graph config protected static $c = array(); // user-configurable data. no pts_Graph* should ever over-write any of this data... should be read-only. protected static $color_cache = array(); protected $d = array(); // the data from the test result / whatever... important data protected $i = array(); // internal data, pts_Graph* can read-write public $svg_dom = null; // TODO: Convert below variables to using $this->[XXX] protected $graph_data = array(); protected $graph_data_raw = array(); protected $graph_data_title = array(); protected $graph_sub_titles = array(); protected $graph_identifiers; protected $graph_title; protected $graph_y_title; protected $is_multi_way_comparison = false; private $test_identifier = null; protected $value_highlights = array(); public function __construct(&$result_object = null, &$result_file = null) { // Initalize Colors $this->i['identifier_size'] = self::$c['size']['identifiers']; // Copy this since it's commonly overwritten $this->i['graph_orientation'] = 'VERTICAL'; $this->i['graph_value_type'] = 'NUMERICAL'; $this->i['hide_graph_identifiers'] = false; $this->i['show_graph_key'] = false; $this->i['show_background_lines'] = false; $this->i['iveland_view'] = false; $this->i['graph_max_value_multiplier'] = 1.285; $this->i['graph_max_value'] = 0; $this->i['bottom_offset'] = 0; $this->i['hide_y_title'] = false; $this->i['key_line_height'] = 0; $this->i['graph_height'] = 0; $this->i['graph_width'] = 0; $this->i['left_start'] = 10; $this->i['left_end_right'] = 10; $this->i['top_start'] = 62; $this->i['top_end_bottom'] = 22; $this->i['mark_count'] = 6; // Number of marks to make on vertical axis $this->i['notes'] = array(); // Reset of setup besides config if($result_object != null) { $test_version = $result_object->test_profile->get_app_version(); if(isset($test_version[2]) && is_numeric($test_version[0])) { $test_version = 'v' . $test_version; } $this->graph_title = trim($result_object->test_profile->get_title() . ' ' . $test_version); $this->graph_y_title = $result_object->test_profile->get_result_scale_formatted(); $this->test_identifier = $result_object->test_profile->get_identifier(); $this->i['graph_proportion'] = $result_object->test_profile->get_result_proportion(); $this->addSubTitle($result_object->get_arguments_description()); } $this->update_graph_dimensions(self::$c['graph']['width'], self::$c['graph']['height'], true); if($result_file != null && $result_file instanceof pts_result_file) { $pts_version = pts_arrays::last_element($result_file->get_system_pts_version()); $this->is_multi_way_comparison = $result_file->is_multi_way_comparison(); } if(!isset($pts_version) || empty($pts_version)) { $pts_version = PTS_VERSION; } $this->i['graph_version'] = 'Phoronix Test Suite ' . $pts_version; } public static function init_graph_config($external_config = null) { self::set_default_graph_values(self::$c); if($external_config && is_array($external_config)) { self::$c = array_merge(self::$c, $external_config); } } public static function set_default_graph_values(&$config) { // Setup config values $config['graph']['width'] = 600; $config['graph']['height'] = 310; $config['graph']['border'] = true; // Colors $config['color']['notches'] = '#757575'; $config['color']['text'] = '#065695'; $config['color']['border'] = '#757575'; $config['color']['main_headers'] = '#231f20'; $config['color']['headers'] = '#231f20'; $config['color']['background'] = '#FEFEFE'; $config['color']['body'] = '#BABABA'; $config['color']['body_text'] = '#FFFFFF'; $config['color']['body_light'] = '#949494'; $config['color']['highlight'] = '#005a00'; $config['color']['alert'] = '#C80000'; $config['color']['paint'] = array('#065695', '#e12128', '#009345', '#1b75bb', '#a3365c', '#2794A9', '#ff5800', '#221914', '#AC008A', '#E00022', '#3A9137', '#00F6FF', '#8A00AC', '#949200', '#797766', '#5598b1', '#555555', '#757575', '#999999', '#CCCDDD'); // Text $config['size']['tick_mark'] = 10; $config['size']['key'] = 9; if(defined('OPENBENCHMARKING_BUILD')) { $config['text']['watermark'] = 'OpenBenchmarking.org'; $config['text']['watermark_url'] = 'http://www.openbenchmarking.org/'; } else { $config['text']['watermark'] = 'PHORONIX-TEST-SUITE.COM'; $config['text']['watermark_url'] = 'http://www.phoronix-test-suite.com/'; } $config['size']['headers'] = 17; $config['size']['bars'] = 11; $config['size']['identifiers'] = 10; $config['size']['sub_headers'] = 11; $config['size']['axis_headers'] = 10; } // // Load Functions // public function loadGraphIdentifiers($data_array) { $this->graph_identifiers = $data_array; } public function addGraphIdentifierNote($identifier, $note) { if(!isset($this->d['identifier_notes'][$identifier]) || empty($this->d['identifier_notes'][$identifier])) { $this->d['identifier_notes'][$identifier] = $note; } else { $this->d['identifier_notes'][$identifier] .= ' - ' . $note; } } public function hideGraphIdentifiers() { $this->i['hide_graph_identifiers'] = true; } public function loadGraphData($data_array) { loadGraphValues($data_array); } public function loadGraphValues($data_array, $data_title = null) { foreach($data_array as &$data_item) { if(is_float($data_item)) { $data_item = round($data_item, 2); } } array_push($this->graph_data, $data_array); if(!empty($data_title)) { array_push($this->graph_data_title, $data_title); } } public function loadGraphRawValues($data_array) { foreach($data_array as &$data_item) { if(is_float($data_item)) { $data_item = round($data_item, 2); } } array_push($this->graph_data_raw, $data_array); } public function addSubTitle($sub_title) { $sub_titles = array_map('trim', explode('|', $sub_title)); foreach($sub_titles as $sub_title) { if(!empty($sub_title)) { array_push($this->graph_sub_titles, $sub_title); } } } public function addTestNote($note, $hover_title = null, $section = null) { array_push($this->i['notes'], array('note' => $note, 'hover-title' => $hover_title, 'section' => $section)); } public function markResultRegressions($threshold) { $this->d['regression_marker_threshold'] = $threshold; } // // Misc Functions // protected function get_paint_color($identifier) { return self::color_cache(0, $identifier, self::$c['color']['paint']); } protected function get_special_paint_color($identifier) { // For now to try to improve the color handling of line graphs, first try to use a pre-defined pool of colors until falling back to the old color code once exhausted // Thanks to ua=42 in the Phoronix Forums for the latest attempt at improving the automated color handling static $predef_line_colors = array('#FFB300', '#803E75', '#FF6800', '#A6BDD7', '#C10020', '#CEA262', '#817066', '#007D34', '#F6768E', '#00538A', '#FF7A5C', '#53377A', '#FF8E00', '#B32851', '#F4C800', '#7F180D', '#93AA00', '#593315', '#F13A13', '#232C16'); if(!isset(self::$color_cache[0][$identifier])) { if(!empty($predef_line_colors)) { self::$color_cache[0][$identifier] = array_pop($predef_line_colors); } else { self::$color_cache[0][$identifier] = $this->get_paint_color($identifier); } } return self::$color_cache[0][$identifier]; } protected function maximum_graph_value() { $real_maximum = 0; foreach($this->graph_data as &$data_r) { $data_max = max($data_r); if(!is_numeric($data_max)) { $data_max = str_repeat(9, strlen($data_max)); } if($data_max > $real_maximum) { $real_maximum = $data_max; } } if(is_numeric($real_maximum)) { if($real_maximum < $this->i['mark_count']) { $maximum = ceil(($real_maximum * 1.35 / $this->i['mark_count']) * $this->i['mark_count']); } else { $maximum = (floor(round($real_maximum * $this->i['graph_max_value_multiplier']) / $this->i['mark_count']) + 1) * $this->i['mark_count']; $maximum = round(ceil($maximum / $this->i['mark_count']), (0 - strlen($maximum) + 2)) * $this->i['mark_count']; } } else { $maximum = 0; } return $maximum; } protected function text_size_bounds($string, $font_size, $minimum_font_size, $bound_width, $bound_height = -1) { list($string_width, $string_height) = pts_svg_dom::estimate_text_dimensions($string, $font_size); while($font_size > $minimum_font_size && $string_width > $bound_width || ($bound_height > 0 && $string_height > $bound_height)) { $font_size -= 0.3; list($string_width, $string_height) = pts_svg_dom::estimate_text_dimensions($string, $font_size); } return $font_size; } public function highlight_values($values) { $this->value_highlights = $values; } protected function update_graph_dimensions($width = -1, $height = -1, $recalculate_offsets = false) { // Allow render area to be increased, but not decreased $this->i['graph_width'] = max($this->i['graph_width'], $width); $this->i['graph_height'] = max($this->i['graph_height'], $height); if($recalculate_offsets) { $this->i['graph_top_end'] = $this->i['graph_height'] - $this->i['top_end_bottom']; $this->i['graph_left_end'] = $this->i['graph_width'] - $this->i['left_end_right']; } } // // Render Functions // public function renderGraph() { $this->render_graph_start(); $this->render_graph_finish(); } public function render_graph_start() { $this->i['graph_max_value'] = $this->maximum_graph_value(); // Make room for tick markings, left hand side if($this->i['iveland_view'] == false) { if($this->i['graph_value_type'] == 'NUMERICAL') { $this->i['left_start'] += $this->text_string_width($this->i['graph_max_value'], self::$c['size']['tick_mark']) + 2; } if($this->i['hide_graph_identifiers']) { $this->i['graph_top_end'] += $this->i['top_end_bottom'] / 2; } $this->i['top_start'] += $this->graph_key_height(); } else { if($this->i['graph_orientation'] == 'HORIZONTAL') { if($this->is_multi_way_comparison && count($this->graph_data_title) > 1) { $longest_r = pts_strings::find_longest_string($this->graph_identifiers); $longest_r = explode(' - ', $longest_r); $plus_extra = 0; if(count($longest_r) > 1) { $plus_extra = count($longest_r) * $this->i['identifier_size'] * 1.2; } $longest_identifier_width = $this->text_string_width($this->i['graph_max_value'], $this->i['identifier_size']) + 60 + $plus_extra; } else { $longest_identifier_width = $this->text_string_width(pts_strings::find_longest_string($this->graph_identifiers), $this->i['identifier_size']) + 8; } $longest_identifier_max = $this->i['graph_width'] * 0.5; $this->i['left_start'] = min($longest_identifier_max, max($longest_identifier_width, 70)); $this->i['left_end_right'] = 15; $this->i['graph_left_end'] = $this->i['graph_width'] - $this->i['left_end_right']; } else if($this->i['graph_value_type'] == 'NUMERICAL') { $this->i['left_start'] += max(20, $this->text_string_width($this->i['graph_max_value'], self::$c['size']['tick_mark']) + 2); } // Pad 8px on top and bottom + title bar + sub-headings $this->i['top_heading_height'] = 16 + self::$c['size']['headers'] + (count($this->graph_sub_titles) * (self::$c['size']['sub_headers'] + 4)); if($this->i['iveland_view']) { // Ensure there is enough room to print PTS logo $this->i['top_heading_height'] = max($this->i['top_heading_height'], 46); } $key_height = $this->graph_key_height(); if($key_height > $this->i['key_line_height']) { // Increase height so key doesn't take up too much room $this->i['graph_height'] += $key_height; $this->i['graph_top_end'] += $key_height; } $this->i['top_start'] = $this->i['top_heading_height'] + $key_height + 16; // + spacing before graph starts $bottom_heading = 14; if($this->i['graph_orientation'] == 'HORIZONTAL') { if($this->is_multi_way_comparison && count($this->graph_data) > 1) { $longest_string = explode(' - ', pts_strings::find_longest_string($this->graph_identifiers)); $longest_string = pts_strings::find_longest_string($longest_string); $rotated_text = round($this->text_string_width($longest_string, $this->i['identifier_size']) * 0.96); $per_identifier_height = max((14 + (22 * count($this->graph_data))), $rotated_text); } else if(count($this->graph_data_title) > 3) { $per_identifier_height = count($this->graph_data_title) * 18; } else { // If there's too much to plot, reduce the size so each graph doesn't take too much room $per_identifier_height = count($this->graph_data[0]) > 10 ? 36 : 46; } $num_identifiers = count($this->graph_identifiers); $this->i['graph_top_end'] = $this->i['top_start'] + ($num_identifiers * $per_identifier_height); // $this->i['top_end_bottom'] $this->i['graph_height'] = $this->i['graph_top_end'] + 25 + $bottom_heading; } else { $this->i['graph_height'] += $bottom_heading + 4; } if(!empty($this->i['notes'])) { $this->i['graph_height'] += $this->note_display_height(); } } // Do the actual work $this->render_graph_pre_init(); $this->render_graph_init(); } public function setAlternateLocation($url) { // this has been replaced by setAlternateView return false; } public function setAlternateView($url) { $this->d['link_alternate_view'] = $url; } public function render_graph_finish() { $this->render_graph_key(); $this->render_graph_base($this->i['left_start'], $this->i['top_start'], $this->i['graph_left_end'], $this->i['graph_top_end']); $this->render_graph_heading(); if($this->i['hide_graph_identifiers'] == false) { $this->render_graph_identifiers(); } if($this->i['graph_value_type'] == 'NUMERICAL') { $this->render_graph_value_ticks($this->i['left_start'], $this->i['top_start'], $this->i['graph_left_end'], $this->i['graph_top_end']); } $this->render_graph_result(); $this->render_graph_post(); } protected function render_graph_pre_init() { return; } protected function render_graph_init() { $this->update_graph_dimensions(); $this->svg_dom = new pts_svg_dom(ceil($this->i['graph_width']), ceil($this->i['graph_height'])); // Background Color if($this->i['iveland_view'] || self::$c['graph']['border']) { $this->svg_dom->add_element('rect', array('x' => 1, 'y' => 1, 'width' => ($this->i['graph_width'] - 2), 'height' => ($this->i['graph_height'] - 1), 'fill' => self::$c['color']['background'], 'stroke' => self::$c['color']['border'], 'stroke-width' => 1)); } else { $this->svg_dom->add_element('rect', array('x' => 0, 'y' => 0, 'width' => $this->i['graph_width'], 'height' => $this->i['graph_height'], 'fill' => self::$c['color']['background'])); } if($this->i['iveland_view'] == false && ($sub_title_count = count($this->graph_sub_titles)) > 1) { $this->i['top_start'] += (($sub_title_count - 1) * (self::$c['size']['sub_headers'] + 4)); } } protected function render_graph_heading($with_version = true) { $href = null; if($this->test_identifier != null) { $href = 'http://openbenchmarking.org/test/' . $this->test_identifier; } // Default to NORMAL if($this->i['iveland_view']) { $this->svg_dom->add_element('rect', array('x' => 0, 'y' => 0, 'width' => $this->i['graph_width'], 'height' => $this->i['top_heading_height'], 'fill' => self::$c['color']['main_headers'])); if(isset($this->graph_title[36])) { // If it's a long string make sure it won't run over the side... while(self::text_string_width($this->graph_title, self::$c['size']['headers']) > ($this->i['graph_left_end'] - 60)) { self::$c['size']['headers'] -= 0.5; } } $this->svg_dom->add_text_element($this->graph_title, array('x' => 6, 'y' => (self::$c['size']['headers'] + 2), 'font-size' => self::$c['size']['headers'], 'fill' => self::$c['color']['background'], 'text-anchor' => 'start', 'xlink:show' => 'new', 'xlink:href' => $href)); foreach($this->graph_sub_titles as $i => $sub_title) { $vertical_offset = 12 + self::$c['size']['headers'] + (($i + 1) * (self::$c['size']['sub_headers'] - 4)); $this->svg_dom->add_text_element($sub_title, array('x' => 6, 'y' => $vertical_offset, 'font-size' => self::$c['size']['sub_headers'], 'fill' => self::$c['color']['background'], 'text-anchor' => 'start')); } $this->svg_dom->add_element('image', array('http_link' => 'http://www.phoronix-test-suite.com/', 'xlink:href' => pts_svg_dom::embed_png_image(PTS_CORE_STATIC_PATH . 'images/pts-77x40-white.png'), 'x' => ($this->i['graph_left_end'] - 77), 'y' => (($this->i['top_heading_height'] / 40 + 2)), 'width' => 77, 'height' => 40)); } else { $this->svg_dom->add_text_element($this->graph_title, array('x' => round($this->i['graph_left_end'] / 2), 'y' => (self::$c['size']['headers'] + 2), 'font-size' => self::$c['size']['headers'], 'fill' => self::$c['color']['main_headers'], 'text-anchor' => 'middle', 'xlink:show' => 'new', 'xlink:href' => $href)); foreach($this->graph_sub_titles as $i => $sub_title) { $this->svg_dom->add_text_element($sub_title, array('x' => round($this->i['graph_left_end'] / 2), 'y' => (31 + (($i + 1) * 18)), 'font-size' => self::$c['size']['sub_headers'], 'fill' => self::$c['color']['main_headers'], 'text-anchor' => 'middle')); } if($with_version) { $this->svg_dom->add_text_element($this->i['graph_version'], array('x' => $this->i['graph_left_end'] , 'y' => ($this->i['top_start'] - 3), 'font-size' => 7, 'fill' => self::$c['color']['body_light'], 'text-anchor' => 'end', 'xlink:show' => 'new', 'xlink:href' => 'http://www.phoronix-test-suite.com/')); } } } protected function render_graph_post() { if($this->i['iveland_view']) { $bottom_heading_start = $this->i['graph_top_end'] + $this->i['bottom_offset'] + 22; $this->svg_dom->add_element('rect', array('x' => 0, 'y' => $bottom_heading_start, 'width' => $this->i['graph_width'], 'height' => ($this->i['graph_height'] - $bottom_heading_start), 'fill' => self::$c['color']['main_headers'])); $this->svg_dom->add_text_element('Powered By ' . $this->i['graph_version'], array('x' => $this->i['graph_left_end'], 'y' => ($bottom_heading_start + self::$c['size']['key'] + 3), 'font-size' => self::$c['size']['key'], 'fill' => self::$c['color']['background'], 'text-anchor' => 'end', 'xlink:show' => 'new', 'xlink:href' => 'http://www.phoronix-test-suite.com/')); if(isset($this->d['link_alternate_view']) && $this->d['link_alternate_view']) { // offer link of image to $this->d['link_alternate_view'] $this->svg_dom->add_element('image', array('http_link' => $this->d['link_alternate_view'], 'xlink:href' => pts_svg_dom::embed_png_image(PTS_CORE_STATIC_PATH . 'images/ob-10x16.png'), 'x' => 4, 'y' => ($bottom_heading_start + 1), 'width' => 10, 'height' => 16)); } if(!empty($this->i['notes'])) { $estimated_height = 0; foreach($this->i['notes'] as $i => $note_r) { $this->svg_dom->add_textarea_element(($i + 1) . '. ' . $note_r['note'], array('x' => 5, 'y' => ($bottom_heading_start + (self::$c['size']['key'] * 2) + 8 + $estimated_height), 'font-size' => (self::$c['size']['key'] - 1), 'fill' => self::$c['color']['background'], 'text-anchor' => 'start', 'xlink:title' => $note_r['hover-title']), $estimated_height); } } } } protected function render_graph_base($left_start, $top_start, $left_end, $top_end) { if($this->i['graph_orientation'] == 'HORIZONTAL' || $this->i['iveland_view']) { $this->svg_dom->draw_svg_line($left_start, $top_start, $left_start, $top_end, self::$c['color']['notches'], 1); $this->svg_dom->draw_svg_line($left_start, $top_end, $left_end, $top_end, self::$c['color']['notches'], 1); if(!empty(self::$c['text']['watermark'])) { $this->svg_dom->add_text_element(self::$c['text']['watermark'], array('x' => $left_end, 'y' => ($top_start - 5), 'font-size' => 7, 'fill' => self::$c['color']['text'], 'text-anchor' => 'end', 'xlink:show' => 'new', 'xlink:href' => self::$c['text']['watermark_url'])); } } else { $this->svg_dom->add_element('rect', array('x' => $left_start, 'y' => $top_start, 'width' => ($left_end - $left_start), 'height' => ($top_end - $top_start), 'fill' => self::$c['color']['body'], 'stroke' => self::$c['color']['notches'], 'stroke-width' => 1)); if(self::$c['text']['watermark'] != null) { $this->svg_dom->add_text_element(self::$c['text']['watermark'], array('x' => ($left_end - 2), 'y' => ($top_start + 12), 'font-size' => 10, 'fill' => self::$c['color']['text'], 'text-anchor' => 'end', 'xlink:show' => 'new', 'xlink:href' => self::$c['text']['watermark_url'])); } } if(!empty($this->graph_y_title) && $this->i['hide_y_title'] == false) { $str = $this->graph_y_title; $offset = 0; if($this->i['graph_proportion'] != null) { $proportion = null; switch($this->i['graph_proportion']) { case 'LIB': $proportion = 'Less Is Better'; $offset += 12; if($this->i['graph_orientation'] == 'HORIZONTAL') { $this->draw_arrow($left_start, $top_start - 8, $left_start + 9, $top_start - 8, self::$c['color']['text'], self::$c['color']['body_light'], 1); } else { $this->draw_arrow($left_start + 4, $top_start - 4, $left_start + 4, $top_start - 11, self::$c['color']['text'], self::$c['color']['body_light'], 1); } break; case 'HIB': $proportion = 'More Is Better'; $offset += 12; if($this->i['graph_orientation'] == 'HORIZONTAL') { $this->draw_arrow($left_start + 9, $top_start - 8, $left_start, $top_start - 8, self::$c['color']['text'], self::$c['color']['body_light'], 1); } else { $this->draw_arrow($left_start + 4, $top_start - 11, $left_start + 4, $top_start - 4, self::$c['color']['text'], self::$c['color']['body_light'], 1); } break; } if($proportion) { if($str) { $str .= ', '; } $str .= $proportion; } } $this->svg_dom->add_text_element($str, array('x' => ($left_start + $offset), 'y' => ($top_start - 5), 'font-size' => 7, 'fill' => self::$c['color']['text'], 'text-anchor' => 'start')); } } protected function render_graph_value_ticks($left_start, $top_start, $left_end, $top_end) { $increment = round($this->i['graph_max_value'] / $this->i['mark_count'], 2); if($this->i['graph_orientation'] == 'HORIZONTAL') { $tick_width = round(($left_end - $left_start) / $this->i['mark_count']); $display_value = 0; for($i = 0; $i < $this->i['mark_count']; $i++) { $px_from_left = $left_start + ($tick_width * $i); if($i != 0) { $this->svg_dom->add_text_element($display_value, array('x' => $px_from_left, 'y' => ($top_end + 5 + self::$c['size']['tick_mark']), 'font-size' => self::$c['size']['tick_mark'], 'fill' => self::$c['color']['text'], 'text-anchor' => 'middle')); $this->svg_dom->draw_svg_line($px_from_left + 2, $top_start, $px_from_left + 2, $top_end - 5, self::$c['color']['body'], 1, array('stroke-dasharray' => '5,5')); $this->svg_dom->draw_svg_line($px_from_left + 2, $top_end - 4, $px_from_left + 2, $top_end + 4, self::$c['color']['notches'], 1); } $display_value += $increment; } } else { $tick_width = round(($top_end - $top_start) / $this->i['mark_count']); $px_from_left_start = $left_start - 5; $px_from_left_end = $left_start + 5; $display_value = 0; for($i = 0; $i < $this->i['mark_count']; $i++) { $px_from_top = round($top_end - ($tick_width * $i)); if($i != 0) { $this->svg_dom->add_text_element($display_value, array('x' => ($px_from_left_start - 4), 'y' => round($px_from_top + (self::$c['size']['tick_mark'] / 2)), 'font-size' => self::$c['size']['tick_mark'], 'fill' => self::$c['color']['text'], 'text-anchor' => 'end')); if($this->i['show_background_lines']) { $this->svg_dom->draw_svg_line($px_from_left_end + 6, $px_from_top + 1, $this->i['graph_left_end'], $px_from_top + 1, self::$c['color']['body_light'], 1, array('stroke-dasharray' => '5,5')); } $this->svg_dom->draw_svg_line($left_start, $px_from_top + 1, $left_end, $px_from_top + 1, self::$c['color']['notches'], 1, array('stroke-dasharray' => '5,5')); $this->svg_dom->draw_svg_line($left_start - 4, $px_from_top + 1, $left_start + 4, $px_from_top + 1, self::$c['color']['notches'], 1); } $display_value += $increment; } } } protected function render_graph_identifiers() { return; } protected function render_graph_result() { return; } protected function graph_key_height() { if(count($this->graph_data_title) < 2 && $this->i['show_graph_key'] == false) { return 0; } $this->i['key_line_height'] = 16; $this->i['key_item_width'] = 16 + $this->text_string_width(pts_strings::find_longest_string($this->graph_data_title), self::$c['size']['key']); $this->i['keys_per_line'] = max(1, floor(($this->i['graph_left_end'] - $this->i['left_start']) / $this->i['key_item_width'])); return ceil(count($this->graph_data_title) / $this->i['keys_per_line']) * $this->i['key_line_height']; } protected function render_graph_key() { if($this->i['key_line_height'] == 0) { return; } $y = $this->i['top_start'] - $this->graph_key_height() - 7; for($i = 0, $key_count = count($this->graph_data_title); $i < $key_count; $i++) { if(!empty($this->graph_data_title[$i])) { $this_color = $this->get_special_paint_color($this->graph_data_title[$i]); if($i != 0 && $i % $this->i['keys_per_line'] == 0) { $y += $this->i['key_line_height']; } $x = $this->i['left_start'] + 13 + ($this->i['key_item_width'] * ($i % $this->i['keys_per_line'])); $this->svg_dom->add_element('rect', array('x' => ($x - 13), 'y' => ($y - 5), 'width' => 10, 'height' => 10, 'fill' => $this_color, 'stroke' => self::$c['color']['notches'], 'stroke-width' => 1)); $this->svg_dom->add_text_element($this->graph_data_title[$i], array('x' => $x, 'y' => ($y + 4), 'font-size' => self::$c['size']['key'], 'fill' => $this_color, 'text-anchor' => 'start')); } } } protected function draw_arrow($tip_x1, $tip_y1, $tail_x1, $tail_y1, $background_color, $border_color = null, $border_width = 0) { $is_vertical = ($tip_x1 == $tail_x1); if($is_vertical) { // Vertical arrow $arrow_length = sqrt(pow(($tail_x1 - $tip_x1), 2) + pow(($tail_y1 - $tip_y1), 2)); $arrow_length_half = $arrow_length / 2; $arrow_points = array( $tip_x1 . ',' . $tip_y1, ($tail_x1 + $arrow_length_half) . ',' . $tail_y1, ($tail_x1 - $arrow_length_half) . ',' . $tail_y1 ); } else { // Horizontal arrow $arrow_length = sqrt(pow(($tail_x1 - $tip_x1), 2) + pow(($tail_y1 - $tip_y1), 2)); $arrow_length_half = $arrow_length / 2; $arrow_points = array( $tip_x1 . ',' . $tip_y1, $tail_x1 . ',' . ($tail_y1 + $arrow_length_half), $tail_x1 . ',' . ($tail_y1 - $arrow_length_half) ); } $this->svg_dom->add_element('polygon', array('points' => implode(' ', $arrow_points), 'fill' => $background_color, 'stroke' => $border_color, 'stroke-width' => $border_width)); } protected function text_string_width($string, $size) { $dimensions = pts_svg_dom::estimate_text_dimensions($string, $size); return $dimensions[0]; } protected function text_string_height($string, $size) { $dimensions = pts_svg_dom::estimate_text_dimensions($string, $size); return $dimensions[1]; } public static function color_cache($ns, $id, &$colors) { //return array_shift($colors); static $color_shift = 0; static $color_shift_size = 120; $i = count(self::$color_cache); $color_shift_size = ($i == 0 ? 120 : 360 / $i); // can't be assigned directly to static var if(!isset(self::$color_cache[$ns][$id])) { if(!isset(self::$color_cache[$ns])) { self::$color_cache[$ns] = array(); } do { if(empty($colors)) { return false; } $hsl = self::color_rgb_to_hsl($colors[0]); $hsl = self::shift_hsl($hsl, $color_shift % 360); $color = self::color_hsl_to_hex($hsl); $color_shift += $color_shift_size; if($color_shift == ($color_shift_size * 3)) { $color_shift_size *= 0.3; $colors[0] = self::color_shade($colors[0], 0.9, 1); } else if($color_shift > 630) { // We have already exhausted the cache pool once array_shift($colors); $color_shift = 0; } } while(in_array($color, self::$color_cache[$ns])); self::$color_cache[$ns][$id] = $color; } return self::$color_cache[$ns][$id]; } public static function color_hex_to_rgb($hex) { $color = hexdec($hex); return array( 'r' => ($color >> 16) & 0xff, 'g' => ($color >> 8) & 0xff, 'b' => $color & 0xff ); } protected function note_display_height() { // This basically figures out how many lines of notes there are times the size of the font key... // additionally, it attempts to figure out if the note will word-wrap to additional lines to accomodate that $note_height = 0; $sections = array(); if(!empty($this->i['notes'])) { foreach($this->i['notes'] as $note) { // If the note isn't at least 36 characters long, assume it's not long enough to word-wrap, so take short-cut for efficiency $note_height += !isset($note['note'][36]) ? (self::$c['size']['key'] + 2) : (ceil($this->text_string_width($note['note'], self::$c['size']['key']) / ($this->i['graph_width'] - 14))) * self::$c['size']['key']; if($note['section'] != null) { array_push($sections, $note['section']); } } $note_height += self::$c['size']['key']; } $note_height += ((count(array_unique($sections)) + 1) * (self::$c['size']['key'] + 6)); return $note_height; } public static function color_hsl_to_hex($hsl) { if($hsl['s'] == 0) { $rgb['r'] = $hsl['l'] * 255; $rgb['g'] = $hsl['l'] * 255; $rgb['b'] = $hsl['l'] * 255; } else { $conv2 = $hsl['l'] < 0.5 ? $hsl['l'] * (1 + $hsl['s']) : ($hsl['l'] + $hsl['s']) - ($hsl['l'] * $hsl['s']); $conv1 = 2 * $hsl['l'] - $conv2; $rgb['r'] = round(255 * self::color_hue_convert($conv1, $conv2, $hsl['h'] + (1 / 3))); $rgb['g'] = round(255 * self::color_hue_convert($conv1, $conv2, $hsl['h'])); $rgb['b'] = round(255 * self::color_hue_convert($conv1, $conv2, $hsl['h'] - (1 / 3))); } return self::color_rgb_to_hex($rgb['r'], $rgb['g'], $rgb['b']); } protected static function color_hue_convert($v1, $v2, $vh) { if($vh < 0) { $vh += 1; } if($vh > 1) { $vh -= 1; } if((6 * $vh) < 1) { return $v1 + ($v2 - $v1) * 6 * $vh; } if((2 * $vh) < 1) { return $v2; } if((3 * $vh) < 2) { return $v1 + ($v2 - $v1) * ((2 / 3 - $vh) * 6); } return $v1; } public static function color_rgb_to_hsl($hex) { $rgb = self::color_hex_to_rgb($hex); foreach($rgb as &$value) { $value = $value / 255; } $min = min($rgb); $max = max($rgb); $delta = $max - $min; $hsl['l'] = ($max + $min) / 2; if($delta == 0) { $hsl['h'] = 0; $hsl['s'] = 0; } else { $hsl['s'] = $delta / ($hsl['l'] < 0.5 ? $max + $min : 2 - $max - $min); $delta_rgb = array(); foreach($rgb as $color => $value) { $delta_rgb[$color] = ((($max - $value) / 6) + ($max / 2)) / $delta; } switch($max) { case $rgb['r']: $hsl['h'] = $delta_rgb['b'] - $delta_rgb['g']; break; case $rgb['g']: $hsl['h'] = (1 / 3) + $delta_rgb['r'] - $delta_rgb['b']; break; case $rgb['b']: default: $hsl['h'] = (2 / 3) + $delta_rgb['g'] - $delta_rgb['r']; break; } $hsl['h'] += $hsl['h'] < 0 ? 1 : 0; $hsl['h'] -= $hsl['h'] > 1 ? 1 : 0; } return $hsl; } public static function shift_hsl($hsl, $rotate_h_degrees = 180) { if($rotate_h_degrees > 0) { $rotate_dec = $rotate_h_degrees / 360; $hsl['h'] = $hsl['h'] <= $rotate_dec ? $hsl['h'] + $rotate_dec : $hsl['h'] - $rotate_dec; } return $hsl; } public static function color_rgb_to_hex($r, $g, $b) { $color = ($r << 16) | ($g << 8) | $b; return '#' . sprintf('%06x', $color); } public static function color_gradient($color1, $color2, $color_weight) { $color1 = self::color_hex_to_rgb($color1); $color2 = self::color_hex_to_rgb($color2); $diff_r = $color2['r'] - $color1['r']; $diff_g = $color2['g'] - $color1['g']; $diff_b = $color2['b'] - $color1['b']; $r = ($color1['r'] + $diff_r * $color_weight); $g = ($color1['g'] + $diff_g * $color_weight); $b = ($color1['b'] + $diff_b * $color_weight); return self::color_rgb_to_hex($r, $g, $b); } public static function color_shade($color, $percent, $mask) { $color = self::color_hex_to_rgb($color); foreach($color as &$color_value) { $color_value = round($color_value * $percent) + round($mask * (1 - $percent)); $color_value = $color_value > 255 ? 255 : $color_value; } return self::color_rgb_to_hex($color['r'], $color['g'], $color['b']); } } ?> phoronix-test-suite/pts-core/objects/pts_Graph/pts_LineGraph.php0000644000175000017500000003205412177277167025227 0ustar michaelmichael. */ class pts_LineGraph extends pts_Graph { public function __construct(&$result_object, &$result_file = null) { parent::__construct($result_object, $result_file); $this->i['show_graph_key'] = true; $this->i['show_background_lines'] = true; $this->i['iveland_view'] = true; $this->i['identifier_width'] = -1; $this->i['graph_max_value_multiplier'] = 1.38; // make room for the average/peak/low table embedded to the top $this->i['min_identifier_size'] = 6.5; $this->i['plot_overview_text'] = true; $this->i['display_select_identifiers'] = false; } protected function render_graph_pre_init() { // Do some common work to this object $graph_identifiers_count = count($this->graph_identifiers); if($graph_identifiers_count > 1) { $identifier_count = $graph_identifiers_count + 1; } else { $identifier_count = 0; foreach(array_keys($this->graph_data) as $i) { $identifier_count = max((count($this->graph_data[$i]) - 1), $identifier_count); } } $this->i['identifier_width'] = $identifier_count > 0 ? (($this->i['graph_left_end'] - $this->i['left_start']) / $identifier_count) : 1; $longest_string = pts_strings::find_longest_string($this->graph_identifiers); $this->i['identifier_size'] = $this->text_size_bounds($longest_string, $this->i['identifier_size'], $this->i['min_identifier_size'], $this->i['identifier_width'] - 4); if($this->i['identifier_size'] <= $this->i['min_identifier_size']) { list($text_width, $text_height) = pts_svg_dom::estimate_text_dimensions($longest_string, $this->i['min_identifier_size'] + 0.5); $this->i['bottom_offset'] += $text_width; $this->update_graph_dimensions($this->i['graph_width'], $this->i['graph_height'] + $text_width); if(($text_height + 4) > $this->i['identifier_width'] && $graph_identifiers_count > 3) { // Show the identifiers as frequently as they will fit $this->i['display_select_identifiers'] = ceil(($text_height + 4) / $this->i['identifier_width']); } } } protected function render_graph_identifiers() { if(!is_array($this->graph_identifiers)) { return; } $px_from_top_end = $this->i['graph_top_end'] + 5; if($this->i['identifier_width'] > 2) { $this->svg_dom->draw_svg_line($this->i['left_start'] + $this->i['identifier_width'], $this->i['graph_top_end'], $this->i['graph_left_end'], $this->i['graph_top_end'], self::$c['color']['notches'], 10, array('stroke-dasharray' => '1,' . ($this->i['identifier_width'] - 1))); } else if($this->i['display_select_identifiers']) { $this->svg_dom->draw_svg_line($this->i['left_start'] + ($this->i['identifier_width'] * $this->i['display_select_identifiers']), $this->i['graph_top_end'], $this->i['graph_left_end'], $this->i['graph_top_end'], self::$c['color']['notches'], 10, array('stroke-dasharray' => '1,' . (($this->i['identifier_width'] * $this->i['display_select_identifiers']) - 1))); } foreach(array_keys($this->graph_identifiers) as $i) { if(is_array($this->graph_identifiers[$i])) { break; } if($this->i['display_select_identifiers'] && ($i % $this->i['display_select_identifiers']) != 0) { // $this->i['display_select_identifiers'] contains the value of how frequently to display identifiers continue; } $px_from_left = $this->i['left_start'] + ($this->i['identifier_width'] * ($i + (count($this->graph_identifiers) > 1 ? 1 : 0))); if($this->i['identifier_size'] <= $this->i['min_identifier_size']) { $this->svg_dom->add_text_element($this->graph_identifiers[$i], array('x' => $px_from_left, 'y' => ($px_from_top_end + 2), 'font-size' => 9, 'fill' => self::$c['color']['headers'], 'text-anchor' => 'start', 'transform' => 'rotate(90 ' . $px_from_left . ' ' . ($px_from_top_end + 2) . ')')); } else { $this->svg_dom->add_text_element($this->graph_identifiers[$i], array('x' => $px_from_left, 'y' => ($px_from_top_end + 10), 'font-size' => $this->i['identifier_size'], 'fill' => self::$c['color']['headers'], 'text-anchor' => 'middle')); } } } protected function get_special_paint_color($identifier) { // For now to try to improve the color handling of line graphs, first try to use a pre-defined pool of colors until falling back to the old color code once exhausted // Thanks to ua=42 in the Phoronix Forums for the latest attempt at improving the automated color handling static $line_color_cache = null; static $predef_line_colors = array('#000000', '#FFB300', '#803E75', '#FF6800', '#A6BDD7', '#C10020', '#CEA262', '#817066', '#007D34', '#F6768E', '#00538A', '#FF7A5C', '#53377A', '#FF8E00', '#B32851', '#F4C800', '#7F180D', '#93AA00', '#593315', '#F13A13', '#232C16'); if(!isset($line_color_cache[$identifier])) { if(!empty($predef_line_colors)) { $line_color_cache[$identifier] = array_shift($predef_line_colors); } else { $line_color_cache[$identifier] = $this->get_paint_color($identifier); } } return $line_color_cache[$identifier]; } protected function renderGraphLines() { $calculations_r = array(); $min_value = $this->graph_data[0][0]; $max_value = $this->graph_data[0][0]; $prev_value = $this->graph_data[0][0]; foreach(array_keys($this->graph_data) as $i_o) { $paint_color = $this->get_special_paint_color((isset($this->graph_data_title[$i_o]) ? $this->graph_data_title[$i_o] : null)); $calculations_r[$paint_color] = array(); $point_counter = count($this->graph_data[$i_o]); $regression_plots = array(); $poly_points = array(); for($i = 0; $i < $point_counter; $i++) { $value = $this->graph_data[$i_o][$i]; if($value < 0 || ($value == 0 && $this->graph_identifiers != null)) { // 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); continue; } $identifier = isset($this->graph_identifiers[$i]) ? $this->graph_identifiers[$i] : null; $std_error = isset($this->graph_data_raw[$i_o][$i]) ? pts_math::standard_error(pts_strings::colon_explode($this->graph_data_raw[$i_o][$i])) : 0; $data_string = isset($this->graph_data_title[$i_o]) ? $this->graph_data_title[$i_o] . ($identifier ? ' @ ' . $identifier : null) . ': ' . $value : null; $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($value > $max_value) { $max_value = $value; } else if($value < $min_value) { $min_value = $value; } if($px_from_left > $this->i['graph_left_end']) { //$px_from_left = $this->i['graph_left_end'] - 1; 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; } array_push($calculations_r[$paint_color], $value); $prev_identifier = $identifier; $prev_value = $value; } $this->draw_graph_line_process($poly_points, $paint_color, $regression_plots, $point_counter); } if($this->i['plot_overview_text']) { $to_display = array(); $to_display[self::$c['color']['notches']] = array(); foreach(array_keys($calculations_r) as $color) { $to_display[$color] = array(); } // in_array($this->graph_y_title, array('Percent', 'Milliwatts', 'Megabytes', 'Celsius', 'MB/s', 'Frames Per Second', 'Seconds', 'Iterations Per Minute')) if(!empty($calculations_r)) { array_push($to_display[self::$c['color']['notches']], 'Average:'); foreach($calculations_r as $color => &$values) { array_push($to_display[$color], (array_sum($values) / count($values))); } // in_array($this->graph_y_title, array('Megabytes', 'Milliwatts', 'Celsius', 'MB/s', 'Frames Per Second', 'Seconds', 'Iterations Per Minute')) if(($this->graph_y_title != 'Percent' || $max_value < 100) && $max_value != $min_value) { array_push($to_display[self::$c['color']['notches']], 'Peak:'); foreach($calculations_r as $color => &$values) { array_push($to_display[$color], max($values)); } } if($min_value > 0 && $max_value != $min_value) { array_push($to_display[self::$c['color']['notches']], 'Low:'); foreach($calculations_r as $color => &$values) { array_push($to_display[$color], min($values)); } } /*if($point_counter > 9 && !in_array($this->graph_y_title, array('Percent'))) { array_push($to_display[self::$c['color']['body_text']], 'Last:'); foreach($calculations_r as $color => &$values) { array_push($to_display[$color], $values[count($values) - 1]); } }*/ // Do the actual rendering of avg / low / med high identifiers $from_left = $this->i['left_start'] + 6; foreach($to_display as $color_key => &$column) { $from_top = $this->i['top_start'] + 10; $longest_string_width = 0; $precision = isset($column[0]) && max($column) > 999 ? 0 : 1; foreach($column as &$write) { if(is_numeric($write)) { $write = pts_math::set_precision($write, $precision); } $this->svg_dom->add_text_element($write, array('x' => $from_left, 'y' => $from_top, 'font-size' => 6.5, 'fill' => $color_key, 'text-anchor' => 'start')); $string_width = $this->text_string_width($write, 6.5); if($string_width > $longest_string_width) { $longest_string_width = $string_width; } $from_top += 10; } $from_left += $longest_string_width + 3; } } } } protected function draw_graph_line_process(&$poly_points, &$paint_color, &$regression_plots, $point_counter) { $poly_points_count = count($poly_points); if($poly_points_count == 0) { // There's nothing to draw return; } $svg_poly = array(); foreach($poly_points as $x_y) { array_push($svg_poly, round($x_y[0]) . ',' . round($x_y[1])); } $svg_poly = implode(' ', $svg_poly); $this->svg_dom->add_element('polyline', array('points' => $svg_poly, 'fill' => 'none', 'stroke' => $paint_color, 'stroke-width' => 2)); foreach($poly_points as $i => $x_y_pair) { if($x_y_pair[0] < ($this->i['left_start'] + 2) || $x_y_pair[0] > ($this->i['graph_left_end'] - 2)) { // Don't draw anything on the left or right hand edges continue; } $plotted_error_bar = false; if($x_y_pair[3] > 0) { $std_error_width = 4; $std_error_rel_size = round(($x_y_pair[3] / $this->i['graph_max_value']) * ($this->i['graph_top_end'] - $this->i['top_start'])); if($std_error_rel_size > 3) { $this->svg_dom->draw_svg_line($x_y_pair[0], $x_y_pair[1] + $std_error_rel_size, $x_y_pair[0], $x_y_pair[1] - $std_error_rel_size, $paint_color, 1); $this->svg_dom->draw_svg_line($x_y_pair[0] - $std_error_width, $x_y_pair[1] - $std_error_rel_size, $x_y_pair[0] + $std_error_width, $x_y_pair[1] - $std_error_rel_size, $paint_color, 1); $this->svg_dom->draw_svg_line($x_y_pair[0] - $std_error_width, $x_y_pair[1] + $std_error_rel_size, $x_y_pair[0] + $std_error_width, $x_y_pair[1] + $std_error_rel_size, $paint_color, 1); $plotted_error_bar = true; } } if(isset($regression_plots[$i]) && $i > 0) { $this->svg_dom->draw_svg_line($x_y_pair[0], $x_y_pair[1] + 6, $x_y_pair[0], $x_y_pair[1] - 6, self::$c['color']['alert'], 4, array('xlink:title' => $regression_plots[$i])); } if($point_counter < 6 || $plotted_error_bar || $i == 0 || $i == ($poly_points_count - 1)) { $this->svg_dom->add_element('ellipse', array('cx' => $x_y_pair[0], 'cy' => $x_y_pair[1], 'rx' => 3, 'ry' => 3, 'fill' => $paint_color, 'stroke' => $paint_color, 'stroke-width' => 1, 'xlink:title' => $x_y_pair[2])); } } $poly_points = array(); } protected function render_graph_result() { $this->renderGraphLines(); } } ?> phoronix-test-suite/pts-core/objects/nye_Xml/pts_test_nye_XmlReader.php0000644000175000017500000000647712202504605026624 0ustar michaelmichael. */ class pts_test_nye_XmlReader extends nye_XmlReader { protected $override_values; protected $block_test_extension_support = false; public function __construct($read_xml) { if(!isset($read_xml[512])) { if(defined('PTS_TEST_PROFILE_PATH') && is_file(PTS_TEST_PROFILE_PATH . $read_xml . '/test-definition.xml')) { $read_xml = PTS_TEST_PROFILE_PATH . $read_xml . '/test-definition.xml'; } else if(substr($read_xml, -4) == '.zip' && is_file($read_xml)) { $zip = new ZipArchive(); if($zip->open($read_xml) === true) { $read_xml = $zip->getFromName('test-definition.xml'); $zip->close(); } } } $this->override_values = array(); parent::__construct($read_xml); } public function validate() { return $this->dom->schemaValidate(PTS_OPENBENCHMARKING_PATH . 'schemas/test-profile.xsd'); } public function block_test_extension_support() { $this->block_test_extension_support = true; } public function overrideXMLValues($test_options) { foreach($test_options as $xml_tag => $value) { $this->overrideXMLValue($xml_tag, $value); } } public function overrideXMLValue($xml_tag, $value) { $this->override_values[$xml_tag] = $value; } public function getOverrideValues() { return $this->override_values; } public function getXMLValue($xml_tag, $fallback_value = false) { if(isset($this->override_values[$xml_tag]) && !empty($this->override_values[$xml_tag])) { return $this->override_values[$xml_tag]; } else { $tag_name = basename($xml_tag); if(isset($this->override_values[$tag_name]) && !empty($this->override_values[$tag_name])) { return $this->override_values[$tag_name]; } } return parent::getXmlValue($xml_tag, $fallback_value); } public function handleXmlZeroTagFallback($xml_tag, $fallback_value) { // Cascading Test Profiles for finding a tag within an XML file being extended by another XML file if($xml_tag == 'PhoronixTestSuite/TestProfile/Extends' || $this->block_test_extension_support) { // Otherwise we'd have an infinite loop return $fallback_value; } $test_extends = $this->getXmlValue('PhoronixTestSuite/TestProfile/Extends'); if(!empty($test_extends) && PTS_IS_CLIENT) { $test_extends = pts_openbenchmarking::evaluate_string_to_qualifier($test_extends, true, 'test'); $test_below_parser = new pts_test_nye_XmlReader($test_extends); $test_below_tag = $test_below_parser->getXMLValue($xml_tag); if(!empty($test_below_tag)) { $fallback_value = $test_below_tag; } } return $fallback_value; } } ?> phoronix-test-suite/pts-core/objects/nye_Xml/pts_config_nye_XmlReader.php0000644000175000017500000000500511564542013027101 0ustar michaelmichael. */ class pts_config_nye_XmlReader extends nye_XmlReader { protected $override_values; public function __construct($new_values = null) { if(is_file(PTS_USER_PATH . 'user-config.xml')) { $file = PTS_USER_PATH . 'user-config.xml'; } else if(PTS_IS_CLIENT && is_file(($t = PTS_CORE_STATIC_PATH . phodevi::read_property('system', 'vendor-identifier') . '-user-config-template.xml'))) { $file = $t; } else if(is_file(PTS_CORE_STATIC_PATH . 'user-config-template.xml')) { $file = PTS_CORE_STATIC_PATH . 'user-config-template.xml'; } else if(is_file(PTS_CORE_STATIC_PATH . 'user-config-defaults.xml')) { $file = PTS_CORE_STATIC_PATH . 'user-config-defaults.xml'; } else { $file = null; } $this->override_values = (is_array($new_values) ? $new_values : false); parent::__construct($file); } public function handleXmlZeroTagFallback($xml_tag, $fallback_value) { static $fallback_reader = null; if($fallback_reader != null || is_file(PTS_CORE_STATIC_PATH . 'user-config-defaults.xml')) { if($fallback_reader == null) { $fallback_reader = new nye_XmlReader(PTS_CORE_STATIC_PATH . 'user-config-defaults.xml'); } $fallback_value = $fallback_reader->getXMLValue($xml_tag); } else if(PTS_IS_CLIENT) { echo "\nUndefined Config Option: $xml_tag\n"; } return $fallback_value; } public function getXMLValue($xml_tag, $fallback_value = false) { if($this->override_values != false) { if(isset($this->override_values[$xml_tag])) { return $this->override_values[$xml_tag]; } else if(isset($this->override_values[($bn = basename($xml_tag))])) { return $this->override_values[$bn]; } } return parent::getXMLValue($xml_tag, $fallback_value); } } ?> phoronix-test-suite/pts-core/objects/nye_Xml/pts_test_downloads_nye_XmlReader.php0000644000175000017500000000207211564542013030666 0ustar michaelmichael. */ class pts_test_downloads_nye_XmlReader extends nye_XmlReader { public function __construct($read_xml) { parent::__construct($read_xml); } public function validate() { return $this->dom->schemaValidate(PTS_OPENBENCHMARKING_PATH . 'schemas/test-profile-downloads.xsd'); } } ?> phoronix-test-suite/pts-core/objects/nye_Xml/pts_results_nye_XmlReader.php0000644000175000017500000000755611564533734027364 0ustar michaelmichael. */ class pts_results_nye_XmlReader extends nye_XmlReader { public function __construct($read_xml) { if(!isset($read_xml[1024]) && defined('PTS_SAVE_RESULTS_PATH') && is_file(PTS_SAVE_RESULTS_PATH . $read_xml . '/composite.xml')) { $read_xml = PTS_SAVE_RESULTS_PATH . $read_xml . '/composite.xml'; } if(defined('PHOROMATIC_BUILD') && !isset($read_xml[1024]) && is_file($read_xml)) { // Work around a nye_XmlReader parsing bug with early Phoromatic versions where \' was done $read_xml = file_get_contents($read_xml); $read_xml = substr($read_xml, strpos($read_xml, '')); } parent::__construct($read_xml); } public function validate() { // on failure get errors from libxml_get_errors(); return $this->dom->schemaValidate(PTS_OPENBENCHMARKING_PATH . 'schemas/result-file.xsd'); } protected function handleXmlZeroTagFallback($xml_tag, $value) { $legacy_spec = array( /* New Tag => Old Tag */ // The below tags were changed during Phoronix Test Suite 3.0 Iveland 'PhoronixTestSuite/Generated/Title' => 'PhoronixTestSuite/Suite/Title', 'PhoronixTestSuite/Generated/Description' => 'PhoronixTestSuite/Suite/Description' ); return isset($legacy_spec[$xml_tag]) ? $this->getXMLValue($legacy_spec[$xml_tag], $value) : $value; } protected function handleXmlZeroTagArrayFallback($xml_tag, $value, $break_depth = -1) { $legacy_spec = array( /* New Tag => Old Tag */ // The below tags were changed during Phoronix Test Suite 3.0 Iveland 'PhoronixTestSuite/System/User' => 'PhoronixTestSuite/System/Author', 'PhoronixTestSuite/System/Identifier' => 'PhoronixTestSuite/System/AssociatedIdentifiers', 'PhoronixTestSuite/System/TimeStamp' => 'PhoronixTestSuite/System/TestDate', 'PhoronixTestSuite/System/Notes' => 'PhoronixTestSuite/System/TestNotes', 'PhoronixTestSuite/System/TestClientVersion' => 'PhoronixTestSuite/System/Version', 'PhoronixTestSuite/Result/Identifier' => 'PhoronixTestSuite/Benchmark/TestName', 'PhoronixTestSuite/Result/Title' => 'PhoronixTestSuite/Benchmark/Name', 'PhoronixTestSuite/Result/Scale' => 'PhoronixTestSuite/Benchmark/Scale', 'PhoronixTestSuite/Result/AppVersion' => 'PhoronixTestSuite/Benchmark/Version', 'PhoronixTestSuite/Result/DisplayFormat' => 'PhoronixTestSuite/Benchmark/ResultFormat', 'PhoronixTestSuite/Result/Proportion' => 'PhoronixTestSuite/Benchmark/Proportion', 'PhoronixTestSuite/Result/Arguments' => 'PhoronixTestSuite/Benchmark/TestArguments', 'PhoronixTestSuite/Result/Description' => 'PhoronixTestSuite/Benchmark/Attributes', 'PhoronixTestSuite/Result/Data' => 'PhoronixTestSuite/Benchmark/Results', 'PhoronixTestSuite/Result/Data/Entry/Identifier' => 'PhoronixTestSuite/Benchmark/Results/Group/Entry/Identifier', 'PhoronixTestSuite/Result/Data/Entry/Value' => 'PhoronixTestSuite/Benchmark/Results/Group/Entry/Value', 'PhoronixTestSuite/Result/Data/Entry/RawString' => 'PhoronixTestSuite/Benchmark/Results/Group/Entry/RawString' ); return isset($legacy_spec[$xml_tag]) ? $this->getXMLArrayValues($legacy_spec[$xml_tag], $break_depth) : $value; } } ?> phoronix-test-suite/pts-core/objects/nye_Xml/pts_parse_results_nye_XmlReader.php0000644000175000017500000000206111564542013030526 0ustar michaelmichael. */ class pts_parse_results_nye_XmlReader extends nye_XmlReader { public function __construct($read_xml) { parent::__construct($read_xml); } public function validate() { return $this->dom->schemaValidate(PTS_OPENBENCHMARKING_PATH . 'schemas/results-parser.xsd'); } } ?> phoronix-test-suite/pts-core/objects/nye_Xml/pts_suite_nye_XmlReader.php0000644000175000017500000000275711726452363027010 0ustar michaelmichael. */ class pts_suite_nye_XmlReader extends nye_XmlReader { public function __construct($read_xml) { if(!isset($xml_file[512]) && defined('PTS_TEST_SUITE_PATH') && is_file(PTS_TEST_SUITE_PATH . $read_xml . '/suite-definition.xml')) { $read_xml = PTS_TEST_SUITE_PATH . $read_xml . '/suite-definition.xml'; } else if(substr($read_xml, -4) == '.zip' && is_file($read_xml)) { $zip = new ZipArchive(); if($zip->open($read_xml) === true) { $read_xml = $zip->getFromName('suite-definition.xml'); $zip->close(); } } parent::__construct($read_xml); } public function validate() { return $this->dom->schemaValidate(PTS_OPENBENCHMARKING_PATH . 'schemas/test-suite.xsd'); } } ?> phoronix-test-suite/pts-core/objects/nye_Xml/nye_XmlWriter.php0000644000175000017500000000654012130644725024750 0ustar michaelmichael. */ class nye_XmlWriter { protected $items; public $dom; public function __construct($xsl_binding = null, $nice_formatting = true) { $this->dom = new DOMDocument('1.0'); $this->dom->formatOutput = PTS_IS_CLIENT && $nice_formatting; //$this->dom->preserveWhiteSpace = false; $this->items = array(); if(PTS_IS_CLIENT && stripos(PTS_PHP_VERSION, 'hiphop') === false) { $pts_comment = $this->dom->createComment(pts_title(true)); $this->dom->appendChild($pts_comment); } if($xsl_binding != null) { $xslt = $this->dom->createProcessingInstruction('xml-stylesheet', 'type="text/xsl" href="' . $xsl_binding . '"'); $this->dom->appendChild($xslt); } } public function addXmlNodeWNE($xml_location, $xml_value = null) { // When Not Empty, add the XML node return empty($xml_value) ? false : $this->addXmlNode($xml_location, $xml_value); } public function addXmlNode($xml_location, $xml_value = null) { $nodes = explode('/', $xml_location); $pointer = &$this->items; for($i = 0, $node_count = count($nodes); $i < $node_count; $i++) { if(!isset($pointer[$nodes[$i]]) || ($i == ($node_count - 2) && isset($pointer[$nodes[$i]][$nodes[($i + 1)]]))) { $pointer[$nodes[$i]] = array(); $pointer[$nodes[$i]][0] = $this->dom->createElement($nodes[$i]); if($i == 0) { $this->dom->appendChild($pointer[$nodes[$i]][0]); } else { $pointer[0]->appendChild($pointer[$nodes[$i]][0]); if($i == ($node_count - 1)) { $t = $this->dom->createTextNode($xml_value); $pointer[$nodes[$i]][0]->appendChild($t); } } } $pointer = &$pointer[$nodes[$i]]; } } public function addXmlNodeFromReader($xml_location, &$xml, $default_value = null) { $value = $xml->getXmlValue($xml_location); $this->addXmlNode($xml_location, (empty($value) ? $default_value : $value)); } public function addXmlNodeFromReaderWNE($xml_location, &$xml) { $value = $xml->getXmlValue($xml_location); $this->addXmlNodeWNE($xml_location, $value); } public function saveXMLFile($to_file) { return $this->dom->save($to_file); } public function getXML() { return $this->dom->saveXML(); } } ?> phoronix-test-suite/pts-core/objects/nye_Xml/nye_XmlReader.php0000644000175000017500000000676612202504535024702 0ustar michaelmichael. */ class nye_XmlReader { protected $tag_fallback = false; // Fallback value if tag is not present protected $file_location = false; public $dom; // The DOM public function __construct($xml_file) { libxml_use_internal_errors(true); $this->dom = new DOMDocument(); // TODO: investigate whether using the LIBXML_COMPACT option on loading actually increases performance if(!isset($xml_file[1024]) && is_file($xml_file)) { $this->dom->load($xml_file); $this->file_location = $xml_file; } else if($xml_file != null) { $this->dom->loadXML($xml_file); } } public function getFileLocation() { return $this->file_location; } public function getXMLValue($xml_tag, $fallback_value = -1) { $steps = explode('/', $xml_tag); $narrow = $this->dom->getElementsByTagName(array_shift($steps)); foreach($steps as $step) { if($narrow->length == 0) { break; } $narrow = $narrow->item(0)->getElementsByTagName($step); } return $narrow->length == 1 ? $narrow->item(0)->nodeValue : $this->handleXmlZeroTagFallback($xml_tag, ($fallback_value === -1 ? $this->tag_fallback : $fallback_value)); } public function getXMLArrayValues($xml_tag, $break_depth = -1) { $steps = explode('/', $xml_tag); $narrow = $this->dom->getElementsByTagName(array_shift($steps)); $values = $this->processXMLArraySteps($steps, $narrow, 0, $break_depth); return isset($values[0]) ? $values : $this->handleXmlZeroTagArrayFallback($xml_tag, $values, $break_depth); } protected function processXMLArraySteps($steps, $narrow, $steps_offset = 0, $break_depth = -1) { $values = array(); for($i = $steps_offset, $c = count($steps); $i < $c && $narrow->length > 0; $i++) { $narrow = $narrow->item(0)->getElementsByTagName($steps[$i]); if($i == $break_depth) { for($x = 0; $x < $break_depth || $x == 0; $x++) { for($j = 0; $j < $narrow->length; $j++) { array_push($values, $this->processXMLArraySteps($steps, $narrow->item($j)->getElementsByTagName($steps[$i + 1]), $i + 2)); } } break; } else if($i == ($c - 2)) { for($j = 0; $j < $narrow->length; $j++) { $extract = $narrow->item($j)->getElementsByTagName($steps[$i + 1]); array_push($values, ($extract->length > 0 ? $extract->item(0)->nodeValue : null)); } break; } } return $values; } protected function handleXmlZeroTagFallback($xml_tag, $fallback_value) { return $fallback_value; } protected function handleXmlZeroTagArrayFallback($xml_tag, $fallback_value, $break_depth = -1) { return $fallback_value; } public function getXML() { return $this->dom->saveXML(); } } ?> phoronix-test-suite/pts-core/objects/phodevi/phodevi_vfs.php0000644000175000017500000001542512117712733024501 0ustar michaelmichael. */ class phodevi_vfs { private $cache; private $options = array( // name => F/C - Cacheable? - File / Command - Additional Checks // F = File, C = Command 'cpuinfo' => array('type' => 'F', 'F' => '/proc/cpuinfo', 'cacheable' => true, 'preserve' => true, 'subsystem' => 'CPU'), 'lscpu' => array('type' => 'C', 'C' => 'lscpu', 'cacheable' => true, 'preserve' => true, 'subsystem' => 'CPU'), 'lsusb' => array('type' => 'C', 'C' => 'lsusb -v', 'cacheable' => false, 'preserve' => true, 'subsystem' => 'System'), 'sensors' => array('type' => 'C', 'C' => 'sensors', 'cacheable' => false, 'preserve' => true, 'subsystem' => 'System'), 'cc' => array('type' => 'C', 'C' => 'cc -v', 'cacheable' => false, 'preserve' => true, 'subsystem' => 'System'), 'scaling_available_frequencies' => array('type' => 'F', 'F' => '/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies', 'cacheable' => false, 'preserve' => true, 'subsystem' => 'CPU'), 'meminfo' => array('type' => 'F', 'F' => '/proc/meminfo', 'cacheable' => true, 'preserve' => true, 'subsystem' => 'Memory'), 'modules' => array('type' => 'F', 'F' => '/proc/modules', 'cacheable' => false, 'preserve' => true, 'subsystem' => 'System'), 'cmdline' => array('type' => 'F', 'F' => '/proc/cmdline', 'cacheable' => true, 'preserve' => true, 'subsystem' => 'System'), 'kernel_version' => array('type' => 'F', 'F' => '/proc/version', 'cacheable' => true, 'preserve' => true, 'subsystem' => 'System'), 'mounts' => array('type' => 'F', 'F' => '/proc/mounts', 'cacheable' => false, 'preserve' => true, 'subsystem' => 'Disk'), 'glxinfo' => array('type' => 'C', 'C' => 'glxinfo', 'cacheable' => true, 'preserve' => true, 'subsystem' => 'GPU'), 'vdpauinfo' => array('type' => 'C', 'C' => 'vdpauinfo', 'cacheable' => true, 'preserve' => true, 'subsystem' => 'GPU'), 'lspci' => array('type' => 'C', 'C' => 'lspci -mmkvvnn', 'cacheable' => true, 'preserve' => true, 'subsystem' => 'System'), 'radeon_pm_info' => array('type' => 'F', 'F' => '/sys/kernel/debug/dri/0/radeon_pm_info', 'cacheable' => false, 'preserve' => true, 'subsystem' => 'GPU'), 'i915_capabilities' => array('type' => 'F', 'F' => '/sys/kernel/debug/dri/0/i915_capabilities', 'cacheable' => true, 'preserve' => true, 'subsystem' => 'GPU'), 'i915_cur_delayinfo' => array('type' => 'F', 'F' => '/sys/kernel/debug/dri/0/i915_cur_delayinfo', 'cacheable' => false, 'preserve' => true, 'subsystem' => 'GPU'), 'i915_drpc_info' => array('type' => 'F', 'F' => '/sys/kernel/debug/dri/0/i915_drpc_info', 'cacheable' => false, 'preserve' => true, 'subsystem' => 'GPU'), 'xorg_log' => array('type' => 'F', 'F' => '/var/log/Xorg.0.log', 'cacheable' => true, 'preserve' => true, 'subsystem' => 'System', 'remove_timestamps' => true), 'xorg_conf' => array('type' => 'F', 'F' => '/etc/X11/xorg.conf', 'cacheable' => true, 'preserve' => true, 'subsystem' => 'System'), 'dmesg' => array('type' => 'C', 'C' => 'dmesg', 'cacheable' => false, 'preserve' => true, 'subsystem' => 'System', 'remove_timestamps' => true), ); public function __construct() { $this->clear_cache(); } public static function cleanse_file(&$file, $name = false) { switch($name) { case 'mounts': foreach(array('ecryptfs_cipher=', 'ecryptfs_sig=', 'ecryptfs_fnek_sig=') as $check) { if(($x = stripos($file, $check)) !== false) { $split_a = substr($file, 0, ($x + strlen($check))); $y = strlen($file); foreach(array(',', ' ', '&', PHP_EOL) as $next) { if(($z = stripos($file, $next, ($x + strlen($check)))) !== false && $z < $y) { $y = $z; } } $file = $split_a . 'XXXX' . substr($file, $y); } } break; default: $file = pts_strings::remove_lines_containing($file, array('Serial N', 'S/N', 'Serial #', 'serial:', 'serial=')); break; } } public function clear_cache() { $this->cache = array(); } public function cache_index() { return array_keys($this->cache); } public function __get($name) { // This assumes that isset() has been called on $name prior to actually trying to get it... if(isset($this->cache[$name])) { return PHP_EOL . $this->cache[$name] . PHP_EOL; } else if(PTS_IS_CLIENT && isset($this->options[$name])) { if($this->options[$name]['type'] == 'F') { $contents = file_get_contents($this->options[$name]['F']); } else if($this->options[$name]['type'] == 'C') { $command = pts_client::executable_in_path(pts_strings::first_in_string($this->options[$name]['C'])); $descriptor_spec = array( 0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w') ); $proc = proc_open($command, $descriptor_spec, $pipes, null, null); $contents = stream_get_contents($pipes[1]); fclose($pipes[1]); $return_value = proc_close($proc); } if(isset($this->options[$name]['remove_timestamps']) && $this->options[$name]['remove_timestamps']) { // remove leading timestamps such as from dmesg and Xorg.0.log $contents = pts_strings::remove_line_timestamps($contents); } if($this->options[$name]['cacheable']) { $this->cache[$name] = $contents; } return PHP_EOL . $contents . PHP_EOL; } return false; } public function __isset($name) { return isset($this->cache[$name]) || (PTS_IS_CLIENT && $this->cache_isset_names($name)); } public function set_cache_item($name, $cache) { $this->cache[$name] = $cache; } protected function cache_isset_names($name) { // Cache the isset call names with their values when checking files/commands since Phodevi will likely hit each one potentially multiple times and little overhead to caching them static $isset_cache; if(!isset($isset_cache[$name])) { $isset_cache[$name] = ($this->options[$name]['type'] == 'F' && is_readable($this->options[$name]['F'])) || ($this->options[$name]['type'] == 'C' && pts_client::executable_in_path(pts_strings::first_in_string($this->options[$name]['C']))); } return $isset_cache[$name]; } } ?> phoronix-test-suite/pts-core/objects/phodevi/phodevi_device_interface.php0000644000175000017500000000300412076642561027155 0ustar michaelmichael. */ abstract class phodevi_device_interface { public static function read_property($identifier) { return false; } public static function read_sensor($identifier) { return false; } public static function device_notes() { // Any important notes about that device subsystem (i.e. for disk the disk scheduler in use) that in the context of PTS will be reported to the test notes area when called return array(); } public static function available_sensors() { return array(); } public static function properties_for_notes() { return array(); } public static function set_property($identifier, $value) { return false; } } ?> phoronix-test-suite/pts-core/objects/phodevi/phodevi_base.php0000664000175000017500000000346412034614216024612 0ustar michaelmichael. */ class phodevi_base { public static function available_hardware_devices() { return array( 'Processor' => 'cpu', 'Motherboard' => 'motherboard', 'Chipset' => 'chipset', 'Memory' => 'memory', 'Disk' => 'disk', 'Graphics' => 'gpu', 'Audio' => 'audio', 'Monitor' => 'monitor', 'Network' => 'network' ); } public static function available_software_components() { return array( 'OS' => array('system', 'operating-system'), 'Kernel' => array('system', 'kernel-string'), 'Desktop' => array('system', 'desktop-environment'), 'Display Server' => array('system', 'display-server'), 'Display Driver' => array('system', 'display-driver-string'), 'OpenGL' => array('system', 'opengl-driver'), 'Compiler' => array('system', 'compiler'), 'File-System' => array('system', 'filesystem'), 'Screen Resolution' => array('gpu', 'screen-resolution-string'), 'System Layer' => array('system', 'system-layer') ); } } ?> phoronix-test-suite/pts-core/objects/phodevi/phodevi_sensor.php0000644000175000017500000000201211461023441025170 0ustar michaelmichael. */ interface phodevi_sensor { public static function get_type(); public static function get_sensor(); public static function get_unit(); public static function support_check(); public static function read_sensor(); } ?> phoronix-test-suite/pts-core/objects/phodevi/phodevi_device_property.php0000644000175000017500000000230411564533734027105 0ustar michaelmichael. */ class phodevi_device_property { private $object_function; private $cache_code; public function __construct($function, $cache_code = false) { $this->object_function = $function; $this->cache_code = $cache_code; } public function get_device_function() { return $this->object_function; } public function cache_code() { return $this->cache_code; } } ?> phoronix-test-suite/pts-core/objects/phodevi/phodevi_cache.php0000644000175000017500000000351211564533734024747 0ustar michaelmichael. */ class phodevi_cache { private $phodevi_cache; private $phodevi_cs; private $phodevi_time; private $storage_dir; private $client_version; public function __construct($phodevi_cache, $storage_dir = null, $client_version = null) { $this->phodevi_cache = $phodevi_cache; $this->phodevi_cs = md5(serialize($phodevi_cache)); // Checksum $this->phodevi_time = time(); $this->storage_dir = $storage_dir; $this->client_version = $client_version; } public function restore_cache($storage_dir = null, $client_version = null) { $restore_cache = null; if(($this->storage_dir == $storage_dir || $storage_dir == null) && $this->client_version == $client_version) { if($this->phodevi_time > (time() - phodevi::system_uptime())) { if(md5(serialize($this->phodevi_cache)) == $this->phodevi_cs) { $restore_cache = $this->phodevi_cache; } } } return $restore_cache; } public function read_cache() { return $this->phodevi_cache; } } ?> phoronix-test-suite/pts-core/objects/phodevi/phodevi.php0000644000175000017500000003513712130605143023614 0ustar michaelmichael. */ class phodevi extends phodevi_base { public static $vfs = false; private static $device_cache = null; private static $smart_cache = null; private static $sensors = null; private static $operating_system = null; private static $graphics = array( 'mesa' => false, 'ati' => false, 'nvidia' => false ); private static $operating_systems = array( 'linux' => false, 'macosx' => false, 'solaris' => false, 'bsd' => false, 'hurd' => false, 'minix' => false, 'windows' => false ); // A variable that modules can use to override Phodevi caching support, etc public static $allow_phodevi_caching = true; const no_caching = 1; const std_caching = 2; const smart_caching = 3; public static function read_name($device) { return phodevi::read_property($device, 'identifier'); } public static function load_sensors() { foreach(glob(dirname(__FILE__) . '/sensors/*') as $sensor_obj_file) { $sensor_obj_name = basename($sensor_obj_file, '.php'); if(!class_exists($sensor_obj_name, false)) { include($sensor_obj_file); } $type = call_user_func(array($sensor_obj_name, 'get_type')); $sensor = call_user_func(array($sensor_obj_name, 'get_sensor')); if($type != null && $sensor != null) { self::$sensors[$type][$sensor] = $sensor_obj_name; } } } public static function available_sensors() { static $available_sensors = null; if($available_sensors == null) { $available_sensors = array(); foreach(self::$sensors as $sensor_type => &$sensor) { foreach(array_keys($sensor) as $sensor_senses) { array_push($available_sensors, array($sensor_type, $sensor_senses)); } } } return $available_sensors; } public static function supported_sensors() { static $supported_sensors = null; if($supported_sensors == null) { $supported_sensors = array(); foreach(self::available_sensors() as $sensor) { if(self::sensor_supported($sensor)) { array_push($supported_sensors, $sensor); } } } return $supported_sensors; } public static function unsupported_sensors() { static $unsupported_sensors = null; if($unsupported_sensors == null) { $unsupported_sensors = array(); $supported_sensors = self::supported_sensors(); foreach(self::available_sensors() as $sensor) { if(!in_array($sensor, $supported_sensors)) { array_push($unsupported_sensors, $sensor); } } } return $unsupported_sensors; } public static function read_sensor($sensor) { $value = false; if(isset(self::$sensors[$sensor[0]][$sensor[1]])) { $value = call_user_func(array(self::$sensors[$sensor[0]][$sensor[1]], 'read_sensor')); } return $value; } public static function read_sensor_unit($sensor) { return call_user_func(array(self::$sensors[$sensor[0]][$sensor[1]], 'get_unit')); } public static function sensor_supported($sensor) { return isset(self::$sensors[$sensor[0]][$sensor[1]]) && call_user_func(array(self::$sensors[$sensor[0]][$sensor[1]], 'support_check')); } public static function sensor_identifier($sensor) { return $sensor[0] . '.' . $sensor[1]; } public static function sensor_name($sensor) { $type = call_user_func(array(self::$sensors[$sensor[0]][$sensor[1]], 'get_type')); $sensor = call_user_func(array(self::$sensors[$sensor[0]][$sensor[1]], 'get_sensor')); if(strlen($type) < 4) { $formatted = strtoupper($type); } else { $formatted = ucwords($type); } switch($formatted) { case 'SYS': $formatted = 'System'; break; case 'HDD': $formatted = 'Drive'; break; } $formatted .= ' '; switch($sensor) { case 'temp': $formatted .= 'Temperature'; break; case 'freq': $formatted .= 'Frequency'; break; case 'memory': $formatted .= 'Memory Usage'; break; case 'power': $formatted .= 'Power Consumption'; break; default: $formatted .= ucwords(str_replace('-', ' ', $sensor)); break; } return $formatted; } public static function system_hardware($return_as_string = true) { return self::system_information_parse(self::available_hardware_devices(), $return_as_string); } public static function system_software($return_as_string = true) { return self::system_information_parse(self::available_software_components(), $return_as_string); } public static function system_id_string() { $components = array(phodevi::read_property('cpu', 'model'), phodevi::read_name('motherboard'), phodevi::read_property('system', 'operating-system'), phodevi::read_property('system', 'compiler')); return base64_encode(implode('__', $components)); } public static function read_device_notes($device) { $devices = phodevi::available_hardware_devices(); if(isset($devices[$device])) { $notes_r = call_user_func(array('phodevi_' . $devices[$device], 'device_notes')); } else { $notes_r = array(); } return is_array($notes_r) ? $notes_r : array(); } public static function read_property($device, $read_property) { $value = false; if(method_exists('phodevi_' . $device, 'read_property')) { $property = call_user_func(array('phodevi_' . $device, 'read_property'), $read_property); if(!($property instanceof phodevi_device_property)) { return false; } $cache_code = $property->cache_code(); if($cache_code != phodevi::no_caching && phodevi::$allow_phodevi_caching && isset(self::$device_cache[$device][$read_property])) { $value = self::$device_cache[$device][$read_property]; } else { $dev_function_r = pts_arrays::to_array($property->get_device_function()); $dev_function = $dev_function_r[0]; $function_pass = array(); for($i = 1; $i < count($dev_function_r); $i++) { array_push($function_pass, $dev_function_r[$i]); } if(method_exists('phodevi_' . $device, $dev_function)) { $value = call_user_func_array(array('phodevi_' . $device, $dev_function), $function_pass); if(!is_array($value) && $value != null) { $value = pts_strings::strip_string($value); if(function_exists('preg_replace')) { $value = preg_replace('/[^(\x20-\x7F)]*/','', $value); } } if($cache_code != phodevi::no_caching) { self::$device_cache[$device][$read_property] = $value; if($cache_code == phodevi::smart_caching) { // TODO: For now just copy the smart cache to other var, but come up with better yet efficient way self::$smart_cache[$device][$read_property] = $value; } } } } } return $value; } public static function set_property($device, $set_property, $pass_args = array()) { $return_value = false; if(method_exists('phodevi_' . $device, 'set_property')) { $return_value = call_user_func(array('phodevi_' . $device, 'set_property'), $set_property, $pass_args); } return $return_value; } public static function create_vfs() { self::$vfs = new phodevi_vfs(); } public static function initial_setup() { // Operating System Detection $supported_operating_systems = pts_types::operating_systems(); $uname_s = strtolower(php_uname('s')); foreach($supported_operating_systems as $os_check) { for($i = 0; $i < count($os_check); $i++) { if(strpos($uname_s, strtolower($os_check[$i])) !== false) // Check for OS { self::$operating_system = $os_check[0]; self::$operating_systems[strtolower($os_check[0])] = true; break; } } if(self::$operating_system != null) { break; } } if(self::operating_system() == false) { self::$operating_system = 'Unknown'; } // OpenGL / graphics detection $graphics_detection = array('NVIDIA', array('ATI', 'AMD', 'fglrx'), array('Mesa', 'SGI')); $opengl_driver = phodevi::read_property('system', 'opengl-vendor') . ' ' . phodevi::read_property('system', 'opengl-driver') . ' ' . phodevi::read_property('system', 'dri-display-driver'); $opengl_driver = trim(str_replace('Corporation', null, $opengl_driver)); // Prevents a possible false positive for ATI being in CorporATIon foreach($graphics_detection as $gpu_check) { if(!is_array($gpu_check)) { $gpu_check = array($gpu_check); } for($i = 0; $i < count($gpu_check); $i++) { if(stripos($opengl_driver, $gpu_check[$i]) !== false) // Check for GPU { self::$graphics[(strtolower($gpu_check[0]))] = true; break; } } } self::load_sensors(); } public static function set_device_cache($cache_array) { if(is_array($cache_array) && !empty($cache_array)) { self::$smart_cache = array_merge(self::$smart_cache, $cache_array); self::$device_cache = array_merge(self::$device_cache, $cache_array); } } public static function clear_cache() { self::$smart_cache = array(); self::$device_cache = array(); } public static function get_phodevi_cache_object($store_dir, $client_version = 0) { return new phodevi_cache(self::$smart_cache, $store_dir, $client_version); } protected static function system_information_parse($component_array, $return_as_string = true) { // Returns string of hardware information $info = array(); foreach($component_array as $string => $id) { if(is_array($id) && count($id) == 2) { $value = self::read_property($id[0], $id[1]); } else { $value = self::read_name($id); } if($value != -1 && !empty($value)) { $info[$string] = $value; } } if($return_as_string) { $info_array = $info; $info = null; foreach($info_array as $type => $value) { if($info != null) { $info .= ', '; } $info .= $type . ': ' . $value; } } return $info; } public static function system_uptime() { // Returns the system's uptime in seconds $uptime = 1; if(is_file('/proc/uptime')) { $uptime = pts_strings::first_in_string(pts_file_io::file_get_contents('/proc/uptime')); } else if(($uptime_cmd = pts_client::executable_in_path('uptime')) != false) { $uptime_counter = 0; $uptime_output = shell_exec($uptime_cmd . ' 2>&1'); $uptime_output = substr($uptime_output, strpos($uptime_output, ' up') + 3); $uptime_output = substr($uptime_output, 0, strpos($uptime_output, ' user')); $uptime_output = substr($uptime_output, 0, strrpos($uptime_output, ',')) . ' '; if(($day_end_pos = strpos($uptime_output, ' day')) !== false) { $day_output = substr($uptime_output, 0, $day_end_pos); $day_output = substr($day_output, strrpos($day_output, ' ') + 1); if(is_numeric($day_output)) { $uptime_counter += $day_output * 86400; } } if(($mins_end_pos = strpos($uptime_output, ' mins')) !== false) { $mins_output = substr($uptime_output, 0, $day_end_pos); $mins_output = substr($mins_output, strrpos($mins_output, ' ') + 1); if(is_numeric($mins_output)) { $uptime_counter += $mins_output * 60; } } if(($time_split_pos = strpos($uptime_output, ':')) !== false) { $hours_output = substr($uptime_output, 0, $time_split_pos); $hours_output = substr($hours_output, strrpos($hours_output, ' ') + 1); $mins_output = substr($uptime_output, $time_split_pos + 1); $mins_output = substr($mins_output, 0, strpos($mins_output, ' ')); if(is_numeric($hours_output)) { $uptime_counter += $hours_output * 3600; } if(is_numeric($mins_output)) { $uptime_counter += $mins_output * 60; } } if(is_numeric($uptime_counter) && $uptime_counter > 0) { $uptime = $uptime_counter; } } return intval($uptime); } public static function cpu_arch_compatible($check_against) { $compatible = true; $this_arch = phodevi::read_property('system', 'kernel-architecture'); $check_against = pts_arrays::to_array($check_against); if(isset($this_arch[2]) && substr($this_arch, -2) == '86') { $this_arch = 'x86'; } if(!in_array($this_arch, $check_against)) { $compatible = false; } return $compatible; } public static function is_vendor_string($vendor) { return isset($vendor[2]) && pts_strings::string_only_contains($vendor, (pts_strings::CHAR_LETTER | pts_strings::CHAR_NUMERIC | pts_strings::CHAR_DECIMAL | pts_strings::CHAR_SPACE | pts_strings::CHAR_DASH)) && !pts_strings::has_in_istring($vendor, array('manufacturer', 'vendor', 'unknown', 'generic', 'warning')) && (!isset($vendor[7]) || strpos($vendor, ' ') !== false || pts_strings::times_occurred($vendor, pts_strings::CHAR_NUMERIC) == 0) && pts_strings::string_contains($vendor, pts_strings::CHAR_LETTER) && (isset($vendor[4]) || pts_strings::times_occurred($vendor, pts_strings::CHAR_LETTER) > 1) && substr($vendor, -1) != '-'; } public static function is_product_string($product) { return phodevi::is_vendor_string($product) && !pts_strings::has_in_istring($product, array('VBOX', 'QEMU', 'Virtual', 'Family', '440BX', 'VMware', ' Gen', 'Core IGP')); } public static function operating_system() { return self::$operating_system; } public static function is_linux() { return self::$operating_systems['linux']; } public static function is_minix() { return self::$operating_systems['minix']; } public static function is_solaris() { return self::$operating_systems['solaris']; } public static function is_bsd() { return self::$operating_systems['bsd']; } public static function is_macosx() { return self::$operating_systems['macosx']; } public static function is_hurd() { return self::$operating_systems['hurd']; } public static function is_windows() { return self::$operating_systems['windows']; } public static function is_mesa_graphics() { return self::$graphics['mesa']; } public static function is_ati_graphics() { return self::$graphics['ati']; } public static function is_nvidia_graphics() { return self::$graphics['nvidia']; } public static function is_root() { return phodevi::read_property('system', 'username') == 'root'; } } phodevi::create_vfs(); if(PTS_IS_CLIENT) { phodevi::initial_setup(); } ?> phoronix-test-suite/pts-core/objects/bilde_renderer/bilde_renderer.php0000644000175000017500000003627511675713421026452 0ustar michaelmichael. */ abstract class bilde_renderer { public $renderer = 'bilde_renderer'; protected $image; protected $image_width = -1; protected $image_height = -1; protected $embed_identifiers = null; protected $uid_count = 1; protected $special_attributes = null; abstract function __construct($width, $height, $embed_identifiers = null); // create the object abstract function html_embed_code($file_name, $attributes = null, $is_xsl = false); abstract function render_image($output_file = null, $quality = 100); abstract function resize_image($width, $height); abstract function destroy_image(); abstract function write_text_left($text_string, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text = false); abstract function write_text_right($text_string, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text = false); abstract function write_text_center($text_string, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text = false); abstract function draw_rectangle($x1, $y1, $width, $height, $background_color); abstract function draw_rectangle_border($x1, $y1, $width, $height, $border_color); abstract function draw_polygon($points, $body_color, $border_color = null, $border_width = 0); abstract function draw_ellipse($center_x, $center_y, $width, $height, $body_color, $border_color = null, $border_width = 0, $default_hide = false); abstract function draw_line($start_x, $start_y, $end_x, $end_y, $color, $line_width = 1, $title = null); abstract function draw_arc($center_x, $center_y, $radius, $offset_percent, $percent, $body_color, $border_color = null, $border_width = 1, $title = null); abstract function png_image_to_type($file); abstract function jpg_image_to_type($file); abstract function image_copy_merge($source_image_object, $to_x, $to_y, $source_x = 0, $source_y = 0, $width = -1, $height = -1); abstract function convert_hex_to_type($hex); abstract function convert_type_to_hex($type); abstract function text_string_dimensions($string, $font_type, $font_size, $predefined_string = false); // // Meta functions that could be implemented within renderer-specifc code if available // public function draw_dashed_line($start_x, $start_y, $end_x, $end_y, $color, $line_width, $dash_length, $blank_length) { if($start_y == $end_y) { $pos = $start_y - ($line_width / 2); for($i = $start_x; $i < $end_x; $i += ($blank_length + $dash_length)) { $this->draw_line($i, $pos, ($i + $dash_length), $pos, $color, $line_width); } } else { $pos = $end_x - ($line_width / 2); for($i = $start_y; $i < $end_y; $i += ($blank_length + $dash_length)) { $this->draw_line($pos, $i, $pos, ($i + $dash_length), $color, $line_width); } } } public function draw_poly_line($x_y_pair_array, $color, $line_width = 1) { $prev_pair = array_shift($x_y_pair_array); foreach($x_y_pair_array as $x_y) { $this->draw_line($prev_pair[0], $prev_pair[1], $x_y[0], $x_y[1], $color, $line_width); $prev_pair = $x_y; } } public function request_uid() { return 'i_' . $this->uid_count++; } public function draw_rectangle_with_border($x1, $y1, $width, $height, $background_color, $border_color, $title = null) { $this->draw_rectangle($x1, $y1, $width, $height, $background_color); $this->draw_rectangle_border($x1, $y1, $width, $height, $border_color); } public function draw_arrow($tip_x1, $tip_y1, $tail_x1, $tail_y1, $background_color, $border_color = null, $border_width = 0) { $is_vertical = ($tip_x1 == $tail_x1); if($is_vertical) { // Vertical arrow $arrow_length = sqrt(pow(($tail_x1 - $tip_x1), 2) + pow(($tail_y1 - $tip_y1), 2)); $arrow_length_half = $arrow_length / 2; $arrow_points = array( $tip_x1, $tip_y1, $tail_x1 + $arrow_length_half, $tail_y1, $tail_x1 - $arrow_length_half, $tail_y1 ); } else { // Horizontal arrow $arrow_length = sqrt(pow(($tail_x1 - $tip_x1), 2) + pow(($tail_y1 - $tip_y1), 2)); $arrow_length_half = $arrow_length / 2; $arrow_points = array( $tip_x1, $tip_y1, $tail_x1, $tail_y1 + $arrow_length_half, $tail_x1, $tail_y1 - $arrow_length_half ); } $this->draw_polygon($arrow_points, $background_color, $border_color, $border_width); } public static function renderer_supported() { // This should be implemented by the different bilde renderers if the renderer is dependent upon some extensions or something else for the support return true; } // // Setup Functions // public static function setup_renderer($requested_renderer, $width, $height, $embed_identifiers = null, $special_attributes = null) { bilde_renderer::setup_font_directory(); $available_renderers = array('PNG', 'JPG', 'GIF', 'SWF', 'SVG', 'SVGZ'); $selected_renderer = 'SVG'; if(isset($_SERVER['HTTP_USER_AGENT'])) { static $browser_renderer = null; if($browser_renderer == null || isset($_REQUEST['force_format'])) { $browser_renderer = bilde_renderer_web::browser_compatibility_check($_SERVER['HTTP_USER_AGENT']); } $requested_renderer = $browser_renderer; } if((($this_renderer = getenv('BILDE_RENDERER')) != false || defined('BILDE_RENDERER') && ($this_renderer = BILDE_RENDERER) || ($this_renderer = $requested_renderer) != null) && in_array($this_renderer, $available_renderers)) { $is_supported = call_user_func(array('bilde_' . strtolower($this_renderer) . '_renderer', 'renderer_supported')); if($is_supported) { $selected_renderer = $this_renderer; } } switch(strtolower($selected_renderer)) { case 'svg': $renderer = new bilde_svg_renderer($width, $height, $embed_identifiers); break; case 'png': $renderer = new bilde_png_renderer($width, $height, $embed_identifiers); break; case 'jpg': $renderer = new bilde_jpg_renderer($width, $height, $embed_identifiers); break; case 'gif': $renderer = new bilde_gif_renderer($width, $height, $embed_identifiers); break; case 'swf': $renderer = new bilde_swf_renderer($width, $height, $embed_identifiers); break; case 'svgz': $renderer = new bilde_svgz_renderer($width, $height, $embed_identifiers); break; } if($special_attributes != null) { $renderer->set_special_attributes($special_attributes); } return $renderer; } public function set_special_attributes($attributes) { $this->special_attributes = $attributes; } public function render_to_file($output_file = null, $quality = 100) { $output_file = str_replace('BILDE_EXTENSION', strtolower($this->get_renderer()), $output_file); return $this->render_image($output_file, $quality); } // // Generic Functions // public static function setup_font_directory() { // Setup directory for TTF Fonts if(getenv('GDFONTPATH') == false) { if(defined('CUSTOM_FONT_DIR')) { putenv('GDFONTPATH=' . CUSTOM_FONT_DIR); } else if(defined('FONT_DIR')) { putenv('GDFONTPATH=' . FONT_DIR); } else if(($font_env = getenv('FONT_DIR')) != false) { putenv('GDFONTPATH=' . $font_env); } else { putenv('GDFONTPATH=' . getcwd()); } } } public static function find_default_ttf_font($find_font = null) { if(!defined('BILDE_DEFAULT_FONT')) { if(is_readable($find_font)) { $default_font = $find_font; } else if(ini_get('open_basedir')) { $default_font = false; } else { $default_font = false; $possible_fonts = array( '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf', '/usr/share/fonts/truetype/freefont/FreeSans.ttf', '/usr/share/fonts/truetype/ttf-bitstream-vera/Vera.ttf', '/usr/share/fonts/dejavu/DejaVuSans.ttf', '/usr/share/fonts/liberation/LiberationSans-Regular.ttf', '/usr/share/fonts/truetype/DejaVuSans.ttf', '/usr/share/fonts/truetype/LiberationSans-Regular.ttf', '/usr/share/fonts/TTF/dejavu/DejaVuSans.ttf', '/usr/share/fonts/TTF/liberation/LiberationSans-Regular.ttf', '/usr/X11/lib/X11/fonts/TrueType/arphic/uming.ttf', '/usr/local/lib/X11/fonts/bitstream-vera/Vera.ttf' ); foreach($possible_fonts as $font_file) { if(is_readable($font_file)) { $default_font = $font_file; break; } } } define('BILDE_DEFAULT_FONT', $default_font); } return BILDE_DEFAULT_FONT; } public function get_renderer() { return $this->renderer; } public function get_image_width() { return $this->image_width; } public function get_image_height() { return $this->image_height; } public function image_file_to_type($file) { $return_type = null; if(is_readable($file)) { $file_extension = strtoupper(substr($file, strrpos($file, '.') + 1)); switch($file_extension) { case 'PNG': $return_type = $this->png_image_to_type($file); break; case 'JPG': case 'JPEG': $return_type = $this->jpg_image_to_type($file); break; } } return $return_type; } public static function soft_text_string_dimensions($text_string, $font_type, $font_size, $predefined_string = false) { bilde_renderer::setup_font_directory(); if(function_exists('imagettfbbox') && $font_type != false) { $box_array = imagettfbbox($font_size, 0, $font_type, $text_string); $box_width = $box_array[4] - $box_array[6]; if($predefined_string) { $box_array = imagettfbbox($font_size, 0, $font_type, 'JAZ@![]()@|_qy'); } $box_height = $box_array[1] - $box_array[7]; } else { // Basic calculation $box_height = 0.75 * $font_size; $box_width = 0.8 * strlen($text_string) * $font_size; // 0.8 now but should be about 1.18 } // Width x Height return array($box_width, $box_height); } public static function color_gradient($color1, $color2, $color_weight) { $color1 = self::color_hex_to_rgb($color1); $color2 = self::color_hex_to_rgb($color2); $diff_r = $color2['r'] - $color1['r']; $diff_g = $color2['g'] - $color1['g']; $diff_b = $color2['b'] - $color1['b']; $r = ($color1['r'] + $diff_r * $color_weight); $g = ($color1['g'] + $diff_g * $color_weight); $b = ($color1['b'] + $diff_b * $color_weight); return self::color_rgb_to_hex($r, $g, $b); } public static function color_shade($color, $percent, $mask) { $color = self::color_hex_to_rgb($color); foreach($color as &$color_value) { $color_value = round($color_value * $percent) + round($mask * (1 - $percent)); $color_value = $color_value > 255 ? 255 : $color_value; } return self::color_rgb_to_hex($color['r'], $color['g'], $color['b']); } public static function color_cache($ns, $id, &$colors) { //return array_shift($colors); static $cache = array(); static $color_shift = 0; static $color_shift_size = 120; $i = count($cache); $color_shift_size = ($i == 0 ? 120 : 360 / $i); // can't be assigned directly to static var if(!isset($cache[$ns][$id])) { if(!isset($cache[$ns])) { $cache[$ns] = array(); } do { if(empty($colors)) { return false; } $hsl = self::color_rgb_to_hsl($colors[0]); $hsl = bilde_renderer::shift_hsl($hsl, $color_shift % 360); $color = bilde_renderer::color_hsl_to_hex($hsl); $color_shift += $color_shift_size; if($color_shift == ($color_shift_size * 3)) { $color_shift_size *= 0.3; $colors[0] = self::color_shade($colors[0], 0.9, 1); } else if($color_shift > 630) { // We have already exhausted the cache pool once array_shift($colors); $color_shift = 0; } } while(in_array($color, $cache[$ns])); $cache[$ns][$id] = $color; } return $cache[$ns][$id]; } public static function color_hex_to_rgb($hex) { $color = hexdec($hex); return array( 'r' => ($color >> 16) & 0xff, 'g' => ($color >> 8) & 0xff, 'b' => $color & 0xff ); } public static function color_hsl_to_hex($hsl) { if($hsl['s'] == 0) { $rgb['r'] = $hsl['l'] * 255; $rgb['g'] = $hsl['l'] * 255; $rgb['b'] = $hsl['l'] * 255; } else { $conv2 = $hsl['l'] < 0.5 ? $hsl['l'] * (1 + $hsl['s']) : ($hsl['l'] + $hsl['s']) - ($hsl['l'] * $hsl['s']); $conv1 = 2 * $hsl['l'] - $conv2; $rgb['r'] = round(255 * self::color_hue_convert($conv1, $conv2, $hsl['h'] + (1 / 3))); $rgb['g'] = round(255 * self::color_hue_convert($conv1, $conv2, $hsl['h'])); $rgb['b'] = round(255 * self::color_hue_convert($conv1, $conv2, $hsl['h'] - (1 / 3))); } return self::color_rgb_to_hex($rgb['r'], $rgb['g'], $rgb['b']); } protected static function color_hue_convert($v1, $v2, $vh) { if($vh < 0) { $vh += 1; } if($vh > 1) { $vh -= 1; } if((6 * $vh) < 1) { return $v1 + ($v2 - $v1) * 6 * $vh; } if((2 * $vh) < 1) { return $v2; } if((3 * $vh) < 2) { return $v1 + ($v2 - $v1) * ((2 / 3 - $vh) * 6); } return $v1; } public static function color_rgb_to_hsl($hex) { $rgb = bilde_renderer::color_hex_to_rgb($hex); foreach($rgb as &$value) { $value = $value / 255; } $min = min($rgb); $max = max($rgb); $delta = $max - $min; $hsl['l'] = ($max + $min) / 2; if($delta == 0) { $hsl['h'] = 0; $hsl['s'] = 0; } else { $hsl['s'] = $delta / ($hsl['l'] < 0.5 ? $max + $min : 2 - $max - $min); $delta_rgb = array(); foreach($rgb as $color => $value) { $delta_rgb[$color] = ((($max - $value) / 6) + ($max / 2)) / $delta; } switch($max) { case $rgb['r']: $hsl['h'] = $delta_rgb['b'] - $delta_rgb['g']; break; case $rgb['g']: $hsl['h'] = (1 / 3) + $delta_rgb['r'] - $delta_rgb['b']; break; case $rgb['b']: default: $hsl['h'] = (2 / 3) + $delta_rgb['g'] - $delta_rgb['r']; break; } $hsl['h'] += $hsl['h'] < 0 ? 1 : 0; $hsl['h'] -= $hsl['h'] > 1 ? 1 : 0; } return $hsl; } public static function shift_hsl($hsl, $rotate_h_degrees = 180) { if($rotate_h_degrees > 0) { $rotate_dec = $rotate_h_degrees / 360; $hsl['h'] = $hsl['h'] <= $rotate_dec ? $hsl['h'] + $rotate_dec : $hsl['h'] - $rotate_dec; } return $hsl; } public static function color_rgb_to_hex($r, $g, $b) { $color = ($r << 16) | ($g << 8) | $b; return '#' . sprintf('%06x', $color); } protected function text_string_width($text_string, $font_type, $font_size) { $dimensions = $this->text_string_dimensions($text_string, $font_type, $font_size); return $dimensions[0]; } protected function text_string_height($text_string, $font_type, $font_size) { $dimensions = $this->text_string_dimensions($text_string, $font_type, $font_size); return $dimensions[1]; } } ?> phoronix-test-suite/pts-core/objects/bilde_renderer/bilde_svgz_renderer.php0000644000175000017500000000245311564533734027516 0ustar michaelmichael. */ class bilde_svgz_renderer extends bilde_svg_renderer { public $renderer = "SVGZ"; public static function renderer_supported() { return function_exists("gzcompress"); } public function render_image($output_file = null, $quality = 100) { $svg_image = parent::render_image(null); return $output_file != null ? ($gz = gzopen($output_file, 'w9')) && gzwrite($gz, $svg_image) && gzclose($gz) : gzcompress($svg_image, 9); } } ?> phoronix-test-suite/pts-core/objects/bilde_renderer/bilde_renderer_web.php0000644000175000017500000000706311632411233027265 0ustar michaelmichael. */ class bilde_renderer_web { public static function browser_compatibility_check($user_agent) { if(isset($_REQUEST['force_format'])) { return $_REQUEST['force_format']; } $user_agent .= ' '; $selected_renderer = 'SVG'; // Yahoo Slurp, msnbot, and googlebot should always be served SVG so no problems there if(($p = strpos($user_agent, 'Gecko/')) !== false) { // Mozilla Gecko-based browser (Firefox, etc) $gecko_date = substr($user_agent, ($p + 6)); $gecko_date = substr($gecko_date, 0, 6); // Around Firefox 3.0 era is best // Firefox 2.0 mostly works except text might not show... if($gecko_date < 200702) { $selected_renderer = 'PNG'; } } else if(($p = strpos($user_agent, 'AppleWebKit/')) !== false) { // Safari, Google Chrome, Google Chromium, etc $webkit_ver = substr($user_agent, ($p + 12)); $webkit_ver = substr($webkit_ver, 0, strpos($webkit_ver, ' ')); // Webkit 532.2 534.6 (WebOS 3.0.2) on WebOS is buggy for SVG // iPhone OS is using 533 right now if($webkit_ver < 533 || strpos($user_agent, 'hpwOS') !== false) { $selected_renderer = 'PNG'; } if(($p = strpos($user_agent, 'Android ')) !== false) { $android_ver = substr($user_agent, ($p + 8), 3); // Android browser doesn't support SVG. // Google bug report 1376 for Android - http://code.google.com/p/android/issues/detail?id=1376 // Looks like it might work though in 3.0 Honeycomb if($android_ver < 3.0) { $selected_renderer = 'PNG'; } } } else if(($p = strpos($user_agent, 'Opera/')) !== false) { // Opera $ver = substr($user_agent, ($p + 6)); $ver = substr($ver, 0, strpos($ver, ' ')); // 9.27, 9.64 displays most everything okay if($ver < 9.27) { $selected_renderer = 'PNG'; } // text-alignment is still fucked as of 11.50/12.0 $selected_renderer = 'PNG'; } else if(($p = strpos($user_agent, 'Epiphany/')) !== false) { // Older versions of Epiphany. Newer versions should report their Gecko or WebKit appropriately $ver = substr($user_agent, ($p + 9)); $ver = substr($ver, 0, 4); if($ver < 2.22) { $selected_renderer = 'PNG'; } } else if(($p = strpos($user_agent, 'KHTML/')) !== false) { // KDE Konqueror as of 4.7 is still broken for SVG $selected_renderer = 'PNG'; } else if(($p = strpos($user_agent, 'MSIE ')) !== false) { $ver = substr($user_agent, ($p + 5), 1); // Microsoft Internet Explorer 9.0 finally seems to do SVG right if($ver < 10 && $ver != 1) { $selected_renderer = 'PNG'; } } else if(strpos($user_agent, 'facebook') !== false) { // Facebook uses this string for its Like/Share crawler, so serve it a PNG so it can use it as an image $selected_renderer = 'PNG'; } return $selected_renderer; } } ?> phoronix-test-suite/pts-core/objects/bilde_renderer/bilde_gif_renderer.php0000644000175000017500000000213511421346354027257 0ustar michaelmichael. */ class bilde_gif_renderer extends bilde_gd_renderer { var $renderer = "GIF"; public function render_image($output_file = null, $quality = 100) { // $quality is not used with GIF format return imagegif($this->image, $output_file); } } ?> phoronix-test-suite/pts-core/objects/bilde_renderer/bilde_swf_renderer.php0000644000175000017500000002101411564533734027316 0ustar michaelmichael. */ class bilde_swf_renderer extends bilde_renderer { private $swf_font = null; public $renderer = "SWF"; public function __construct($width, $height, $embed_identifiers = "") { $this->image = new SWFMovie(); $this->image_width = $width; $this->image_height = $height; $this->image->setDimension($width, $height); $this->swf_font = new SWFFont("_sans"); // TODO: Implement better font support } public static function renderer_supported() { return extension_loaded("ming"); } public function html_embed_code($file_name, $attributes = null, $is_xsl = false) { $file_name = str_replace("BILDE_EXTENSION", strtolower($this->get_renderer()), $file_name); $attributes = pts_arrays::to_array($attributes); $attributes["value"] = $file_name; $attributes["src"] = $file_name; if($is_xsl) { $html = ""; foreach($attributes as $option => $value) { $html .= "" . $value . ""; } $html .= ""; foreach($attributes as $option => $value) { $html .= "" . $value . ""; } $html .= ""; } else { $html = " $value) { $html .= $option . "=\"" . $value . "\" "; } $html .= "> $value) { $html .= $option . "=\"" . $value . "\" "; } $html .= ">"; } return $html; } public function render_image($output_file = null, $quality = 100) { return $this->image->save($output_file); } public function resize_image($width, $height) { $this->image_width = $width; $this->image_height = $height; $this->image->setDimension($width, $height); } public function destroy_image() { $this->image = null; } public function write_text_left($text_string, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text = false) { $this->write_swf_text($text_string, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text, "LEFT"); } public function draw_arc($center_x, $center_y, $radius, $offset_percent, $percent, $body_color, $border_color = null, $border_width = 1, $title = null) { return false; // TODO: implement } public function write_text_right($text_string, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text = false) { $this->write_swf_text($text_string, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text, "RIGHT"); } public function write_text_center($text_string, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text = false) { $this->write_swf_text($text_string, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text, "CENTER"); } public function draw_rectangle($x1, $y1, $width, $height, $background_color) { $points = array( $x1, $y1, $width, $y1, $width, $height, $x1, $height ); $this->draw_polygon($points, $background_color, $background_color, 1); } public function draw_rectangle_border($x1, $y1, $width, $height, $border_color) { $points = array( $x1, $y1, $width, $y1, $width, $height, $x1, $height ); $this->draw_polygon($points, null, $border_color, 1); } public function draw_polygon($points, $body_color, $border_color = null, $border_width = 0) { $poly = new SWFShape(); if(!empty($body_color)) { $poly->setLeftFill($body_color[0], $body_color[1], $body_color[2]); } if(!empty($border_color) && $border_width > 0) { $poly->setLine($border_width, $border_color[0], $border_color[1], $border_color[2]); } $point_pairs = array(); $this_pair = array(); foreach($points as $one_point) { array_push($this_pair, $one_point); if(count($this_pair) == 2) { array_push($point_pairs, $this_pair); $this_pair = array(); } } if(count($point_pairs) > 1) { $poly->movePenTo($point_pairs[0][0], $point_pairs[0][1]); for($i = 1; $i < count($point_pairs); $i++) { $poly->drawLineTo($point_pairs[$i][0], $point_pairs[$i][1]); } $poly->drawLineTo($point_pairs[0][0], $point_pairs[0][1]); } $this->image->add($poly); } public function draw_ellipse($center_x, $center_y, $width, $height, $body_color, $border_color = null, $border_width = 0, $default_hide = false) { if($default_hide == true) { return false; } if($width > $height) { $base_size = $width; } else { $base_size = $height; } $ellipse = new SWFShape(); $ellipse->setLine($border_width, $border_color[0], $border_color[1], $border_color[2]); $ellipse->setRightFill($body_color[0], $body_color[1], $body_color[2]); $ellipse->drawCircle($base_size / 2); $added = $this->image->add($ellipse); $added->moveTo($center_x, $center_y); $added->scaleTo(($width / $base_size), ($height / $base_size)); } public function draw_line($start_x, $start_y, $end_x, $end_y, $color, $line_width = 1, $title = null) { $line = new SWFShape(); $line->setLine(1, $color[0], $color[1], $color[2]); $line->movePenTo($start_x, $start_y); $line->drawLineTo($end_x, $end_y); $added = $this->image->add($line); } public function png_image_to_type($file) { return new SWFBitmap(fopen($file, "rb")); } public function jpg_image_to_type($file) { return new SWFBitmap(fopen($file, "rb")); } public function image_copy_merge($source_image_object, $to_x, $to_y, $source_x = 0, $source_y = 0, $width = -1, $height = -1) { // TODO: $source_x, $source_y, $width, $height need to be implemented $added = $this->image->add($source_image_object); $added->moveTo($to_x, $to_y); } public function convert_hex_to_type($hex) { return array(hexdec(substr($hex, 1, 2)), hexdec(substr($hex, 3, 2)), hexdec(substr($hex, 5, 2))); } public function convert_type_to_hex($type) { return '#' . dexhec($type[0]) . dexhec($type[1]) . dexhec($type[2]); } public function text_string_dimensions($string, $font_type, $font_size, $predefined_string = false) { return array(0, 0); } // Privates private function write_swf_text($text_string, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text, $orientation = "LEFT") { switch($orientation) { case "CENTER": $align = SWFTEXTFIELD_ALIGN_CENTER; break; case "RIGHT": if($bound_x1 == $bound_x2) { $bound_x1 -= $this->image_width; } $align = SWFTEXTFIELD_ALIGN_RIGHT; break; case "LEFT": default: $align = SWFTEXTFIELD_ALIGN_LEFT; break; } // TODO: Implement $font_type, $rotate_text support $t = new SWFTextField(); $t->setFont($this->swf_font); $t->setColor($font_color[0], $font_color[1], $font_color[2]); $t->setHeight($font_size); if(($width = abs($bound_x1 - $bound_x2)) > 0) { $t->setBounds(abs($bound_x1 - $bound_x2), $font_size); } $t->align($align); $t->addString($text_string); $added = $this->image->add($t); $added->moveTo($bound_x1, $bound_y1); } } ?> phoronix-test-suite/pts-core/objects/bilde_renderer/bilde_jpg_renderer.php0000644000175000017500000000210211564533734027274 0ustar michaelmichael. */ class bilde_jpg_renderer extends bilde_gd_renderer { public $renderer = "JPG"; public function render_image($output_file = null, $quality = 100) { return imagejpeg($this->image, $output_file, $quality); } } ?> phoronix-test-suite/pts-core/objects/bilde_renderer/bilde_png_renderer.php0000644000175000017500000000241011564533734027302 0ustar michaelmichael. */ class bilde_png_renderer extends bilde_gd_renderer { public $renderer = "PNG"; public function render_image($output_file = null, $quality = 100) { $quality = floor(9 - (($quality / 100) * 9)); // calculate compression level if(defined("BILDE_IMAGE_INTERLACING")) { imageinterlace($this->image, BILDE_IMAGE_INTERLACING); } return imagepng($this->image, $output_file, $quality); } } ?> phoronix-test-suite/pts-core/objects/bilde_renderer/bilde_svg_renderer.php0000644000175000017500000004676111675757460027345 0ustar michaelmichael. */ /* draw_rectangle*: $this->svg_dom->add_element('rect', array('x' => 0, 'y' => 0, 'width' => $this->graph_attr_width, 'height' => $this->graph_attr_height, 'fill' => $this->graph_color_background, 'stroke' => $this->graph_color_border, 'stroke-width' => 1)); write_text_left: $this->svg_dom->add_text_element($text, array('x' => 0, 'y' => 0, 'font-size' => $font_size, 'fill' => $color, 'text-anchor' => 'start', 'dominant-baseline' => 'middle')); write_text_right: $this->svg_dom->add_text_element($text, array('x' => 0, 'y' => 0, 'font-size' => $font_size, 'fill' => $color, 'text-anchor' => 'end', 'dominant-baseline' => 'middle')); write_text_center: $this->svg_dom->add_text_element($text, array('x' => 0, 'y' => 0, 'font-size' => $font_size, 'fill' => $color, 'text-anchor' => 'middle', 'dominant-baseline' => 'text-before-edge')); draw_line: draw_ellipse image: $this->svg_dom->add_element('image', array('xlink:href' => $img, 'x' => 0, 'y' => 0, 'width' => $this->graph_attr_width, 'height' => $this->graph_attr_height)); $this->svg_dom->draw_svg_arc($center_x, $center_y, $radius, $offset_percent, $percent, array('fill' => $body_color, 'stroke' => $border_color, 'stroke-width' => $border_width)); */ class bilde_svg_renderer extends bilde_renderer { public $renderer = 'SVG'; private $svg = null; public function __construct($width, $height, $embed_identifiers = null) { $this->image_width = $width; $this->image_height = $height; $this->embed_identifiers = $embed_identifiers; $dom = new DOMImplementation(); $dtd = $dom->createDocumentType('svg', '-//W3C//DTD SVG 1.1//EN', 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'); $this->image = $dom->createDocument(null, null, $dtd); $this->image->formatOutput = PTS_IS_CLIENT; $pts_comment = $this->image->createComment(pts_title(true) . ' [ http://www.phoronix-test-suite.com/ ]'); $this->image->appendChild($pts_comment); $this->svg = $this->image->createElementNS('http://www.w3.org/2000/svg', 'svg'); $this->svg->setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); $this->svg->setAttribute('version', '1.1'); $this->svg->setAttribute('font-family', 'sans-serif'); $this->image->appendChild($this->svg); } public static function renderer_supported() { return true; } public function html_embed_code($file_name, $attributes = null, $is_xsl = false) { $file_name = str_replace('BILDE_EXTENSION', 'svg', $file_name); $attributes = pts_arrays::to_array($attributes); $attributes['data'] = $file_name; if($is_xsl) { $html = ''; foreach($attributes as $option => $value) { $html .= '' . $value . ''; } $html .= ''; } else { $html = ' $value) { $html .= $option . '="' . $value . '" '; } $html .= '/>'; } return $html; } public function resize_image($width, $height) { $this->image_width = $width; $this->image_height = $height; } public function render_image($output_file = null, $quality = 100) { if($this->image == null) { return false; } $this->svg->setAttribute('viewbox', '0 0 ' . $this->image_width . ' ' . $this->image_height); $this->svg->setAttribute('width', $this->image_width); $this->svg->setAttribute('height', $this->image_height); $svg_image = $this->image->saveXML(); return $output_file != null ? @file_put_contents($output_file, $svg_image) : $svg_image; } public function destroy_image() { $this->image = null; } public function write_text_left($text, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate = false) { $font_size += 1; $text_element = $this->image->createElement('text'); $text_element->setAttribute('x', round($bound_x1)); $text_element->setAttribute('y', round($bound_y1)); $text_element->setAttribute('font-size', $font_size); if($rotate != false) { $rotate = ($rotate === true ? 90 : $rotate); $text_element->setAttribute('transform', "rotate($rotate $bound_x1 $bound_y1)"); } $text_element->setAttribute('text-anchor', 'start'); $text_element->setAttribute('dominant-baseline', 'middle'); $text_element->setAttribute('fill', $font_color); $string = $this->image->createTextNode($text); $text_element->appendChild($string); if($text instanceof pts_graph_ir_value) { if($text->get_attribute('title') != null) { $text_element->setAttribute('xlink:title', $text->get_attribute('title')); } if($text->get_attribute('font-weight') != null) { $text_element->setAttribute('font-weight', $text->get_attribute('font-weight')); } if($text->get_attribute('href') != null) { $link = $this->image->createElement('a'); $link->setAttribute('xlink:href', $text->get_attribute('href')); $link->setAttribute('xlink:show', ($text->get_attribute('show') ? $text->get_attribute('show') : 'new')); $link->appendChild($text_element); $this->svg->appendChild($link); return; } } $this->svg->appendChild($text_element); } public function write_text_right($text, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate = false) { $font_size += 1; $text_element = $this->image->createElement('text'); $text_element->setAttribute('x', round($bound_x2)); $text_element->setAttribute('y', round($bound_y2)); $text_element->setAttribute('font-size', $font_size); if($rotate != false) { $rotate = ($rotate === true ? 90 : $rotate); $text_element->setAttribute('transform', "rotate($rotate $bound_x1 $bound_y1)"); } $text_element->setAttribute('text-anchor', 'end'); $text_element->setAttribute('dominant-baseline', 'middle'); $text_element->setAttribute('fill', $font_color); $string = $this->image->createTextNode($text); $text_element->appendChild($string); if($text instanceof pts_graph_ir_value) { if($text->get_attribute('title') != null) { $text_element->setAttribute('xlink:title', $text->get_attribute('title')); } if($text->get_attribute('font-weight') != null) { $text_element->setAttribute('font-weight', $text->get_attribute('font-weight')); } if($text->get_attribute('href') != null) { $link = $this->image->createElement('a'); $link->setAttribute('xlink:href', $text->get_attribute('href')); $link->setAttribute('xlink:show', 'new'); $link->appendChild($text_element); $this->svg->appendChild($link); return; } } $this->svg->appendChild($text_element); } public function write_text_center($text, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate = false) { $font_size += 1; $bound_x1 = round(($bound_x1 != $bound_x2) ? abs($bound_x2 - $bound_x1) / 2 + $bound_x1 : $bound_x1); $bound_y1 = round(($bound_y1 != $bound_y2) ? abs($bound_y2 - $bound_y1) / 2 + $bound_y1 : $bound_y1); $text_element = $this->image->createElement('text'); $text_element->setAttribute('x', $bound_x1); $text_element->setAttribute('y', $bound_y1); $text_element->setAttribute('font-size', $font_size); $text_element->setAttribute('text-anchor', 'middle'); if($rotate != false) { $rotate = ($rotate === true ? 90 : $rotate); $text_element->setAttribute('transform', "rotate($rotate $bound_x1 $bound_y1)"); } $text_element->setAttribute('dominant-baseline', 'text-before-edge'); $text_element->setAttribute('fill', $font_color); $string = $this->image->createTextNode($text); $text_element->appendChild($string); if($text instanceof pts_graph_ir_value) { if($text->get_attribute('title') != null) { $text_element->setAttribute('xlink:title', $text->get_attribute('title')); } if($text->get_attribute('font-weight') != null) { $text_element->setAttribute('font-weight', $text->get_attribute('font-weight')); } if($text->get_attribute('href') != null) { $link = $this->image->createElement('a'); $link->setAttribute('xlink:href', $text->get_attribute('href')); $link->setAttribute('xlink:show', 'new'); $link->appendChild($text_element); $this->svg->appendChild($link); return; } } $this->svg->appendChild($text_element); } public function draw_rectangle_with_border($x1, $y1, $width, $height, $background_color, $border_color, $title = null) { $width = $width - $x1; $height = $height - $y1; $x1 += $width < 0 ? $width : 0; $y1 += $height < 0 ? $height : 0; $rect = $this->image->createElement('rect'); $rect->setAttribute('x', $x1); $rect->setAttribute('y', $y1); $rect->setAttribute('width', $width); $rect->setAttribute('height', $height); $rect->setAttribute('fill', $background_color); $rect->setAttribute('stroke', $border_color); $rect->setAttribute('stroke-width', 1); if($title != null) { $rect->setAttribute('xlink:title', $title); } $this->svg->appendChild($rect); } public function draw_rectangle($x1, $y1, $width, $height, $background_color) { $width = $width - $x1; $height = $height - $y1; $x1 += $width < 0 ? $width : 0; $y1 += $height < 0 ? $height : 0; $rect = $this->image->createElement('rect'); $rect->setAttribute('x', $x1); $rect->setAttribute('y', $y1); $rect->setAttribute('width', $width); $rect->setAttribute('height', $height); $rect->setAttribute('fill', $background_color); $this->svg->appendChild($rect); } public function draw_rectangle_gradient($x1, $y1, $width, $height, $color, $next_color) { $width = $width - $x1; $height = $height - $y1; $x1 += $width < 0 ? $width : 0; $y1 += $height < 0 ? $height : 0; static $gradient_count = 1; $gradient = $this->image->createElement('linearGradient'); $gradient->setAttribute('id', 'g_' . $gradient_count); $gradient->setAttribute('x1', '0%'); $gradient->setAttribute('y1', '0%'); $gradient->setAttribute('x2', '100%'); $gradient->setAttribute('y2', '0%'); $stop = $this->image->createElement('stop'); $stop->setAttribute('offset', '0%'); $stop->setAttribute('style', 'stop-color: ' . $color .'; stop-opacity: 1;'); $gradient->appendChild($stop); $stop = $this->image->createElement('stop'); $stop->setAttribute('offset', '100%'); $stop->setAttribute('style', 'stop-color: ' . $next_color .'; stop-opacity: 1;'); $gradient->appendChild($stop); $defs = $this->image->createElement('defs'); $defs->appendChild($gradient); $this->svg->appendChild($defs); $rect = $this->image->createElement('rect'); $rect->setAttribute('x', $x1); $rect->setAttribute('y', $y1); $rect->setAttribute('width', $width); $rect->setAttribute('height', $height); //$rect->setAttribute('fill', $background_color); $rect->setAttribute('style', 'fill:url(#g_' . $gradient_count . ')'); $gradient_count++; $this->svg->appendChild($rect); } public function draw_rectangle_border($x1, $y1, $width, $height, $border_color) { $width = $width - $x1; $height = $height - $y1; $x1 += $width < 0 ? $width : 0; $y1 += $height < 0 ? $height : 0; $rect = $this->image->createElement('rect'); $rect->setAttribute('x', $x1); $rect->setAttribute('y', $y1); $rect->setAttribute('width', $width); $rect->setAttribute('height', $height); $rect->setAttribute('fill', 'none'); $rect->setAttribute('stroke', $border_color); $rect->setAttribute('stroke-width', 1); $this->svg->appendChild($rect); } public function draw_arc($center_x, $center_y, $radius, $offset_percent, $percent, $body_color, $border_color = null, $border_width = 1, $title = null, $dash = false) { $deg = ($percent * 360); $offset_deg = ($offset_percent * 360); $arc = $percent > 0.5 ? 1 : 0; $p1_x = round(cos(deg2rad($offset_deg)) * $radius) + $center_x; $p1_y = round(sin(deg2rad($offset_deg)) * $radius) + $center_y; $p2_x = round(cos(deg2rad($offset_deg + $deg)) * $radius) + $center_x; $p2_y = round(sin(deg2rad($offset_deg + $deg)) * $radius) + $center_y; $path = $this->image->createElement('path'); $path->setAttribute('d', "M$center_x,$center_y L$p1_x,$p1_y A$radius,$radius 0 $arc,1 $p2_x,$p2_y Z"); $path->setAttribute('fill', $body_color); $path->setAttribute('stroke', $border_color); $path->setAttribute('stroke-width', $border_width); $path->setAttribute('stroke-linejoin', 'round'); if($dash) { $path->setAttribute('stroke-dasharray', '10,20'); } if($title != null) { $path->setAttribute('xlink:title', $title); } $this->svg->appendChild($path); } public function draw_polygon($points, $body_color, $border_color = null, $border_width = 0, $title = null) { $point_pairs = array(); $this_pair = array(); if(isset($points[0]) && is_array($points[0]) && count($points[0]) >= 2) { foreach($points as $point_set) { array_push($point_pairs, implode(',', array_slice($point_set, 0, 2))); } } else { foreach($points as $one_point) { array_push($this_pair, $one_point); if(count($this_pair) == 2) { $pair = implode(',', $this_pair); array_push($point_pairs, $pair); $this_pair = array(); } } } $polygon = $this->image->createElement('polygon'); $polygon->setAttribute('fill', $body_color); if($border_width > 0) { $polygon->setAttribute('stroke', $border_color); $polygon->setAttribute('stroke-width', $border_width); $polygon->setAttribute('points', implode(' ', $point_pairs)); } if($title != null) { $polygon->setAttribute('xlink:title', $title); /*static $id_counter = 0; $id_counter++; $polygon->setAttribute('id', 'phover' . $id_counter); $text = $this->image->createElement('text'); $text->setAttribute('id', 'po' . $id_counter); $text->setAttribute('fill', $border_color); //$text->setAttribute('font-size', '30'); $text->setAttribute('visibility', 'hidden'); $xy = explode(',', $point_pairs[0]); $text->setAttribute('x', array_shift($xy)); $text->setAttribute('y', array_shift($xy)); $string = $this->image->createTextNode($title); $text->appendChild($string); $set = $this->image->createElement('set'); $set->setAttribute('attributeName', 'visibility'); $set->setAttribute('from', 'hidden'); $set->setAttribute('to', 'visible'); $set->setAttribute('begin', 'phover' . $id_counter . '.mouseover'); $set->setAttribute('end', 'phover' . $id_counter . '.mouseout'); $text->appendChild($set); $this->svg->appendChild($polygon); $this->svg->appendChild($text);*/ } $this->svg->appendChild($polygon); } public function draw_ellipse($center_x, $center_y, $width, $height, $body_color, $border_color = null, $border_width = 0, $default_hide = false, $title = null) { $ellipse = $this->image->createElement('ellipse'); $ellipse->setAttribute('cx', $center_x); $ellipse->setAttribute('cy', $center_y); $ellipse->setAttribute('rx', floor($width / 2)); $ellipse->setAttribute('ry', floor($height / 2)); $ellipse->setAttribute('stroke', $border_color); $ellipse->setAttribute('fill', $body_color); $ellipse->setAttribute('stroke-width', $border_width); if($title != null) { $ellipse->setAttribute('xlink:title', $title); } if($default_hide) { return; // TODO: get working correctly $in = $this->image->createElement('set'); $in->setAttribute('attributeName', 'stroke-opacity'); $in->setAttribute('from', 0); $in->setAttribute('to', '1'); $in->setAttribute('begin', 'mouseover'); $in->setAttribute('end', 'mouseout'); $ellipse->appendChild($in); $out = $this->image->createElement('set'); $out->setAttribute('attributeName', 'fill-opacity'); $out->setAttribute('from', 0); $out->setAttribute('to', 1); $out->setAttribute('begin', 'mouseover'); $out->setAttribute('end', 'mouseout'); $ellipse->appendChild($out); } $this->svg->appendChild($ellipse); } public function draw_line($start_x, $start_y, $end_x, $end_y, $color, $line_width = 1, $title = null) { $line = $this->image->createElement('line'); $line->setAttribute('x1', $start_x); $line->setAttribute('y1', $start_y); $line->setAttribute('x2', $end_x); $line->setAttribute('y2', $end_y); $line->setAttribute('stroke', $color); $line->setAttribute('stroke-width', $line_width); if($title != null) { $line->setAttribute('xlink:title', $title); } $this->svg->appendChild($line); } public function draw_dashed_line($start_x, $start_y, $end_x, $end_y, $color, $line_width, $dash_length, $blank_length) { $line = $this->image->createElement('line'); $line->setAttribute('x1', round($start_x)); $line->setAttribute('y1', round($start_y)); $line->setAttribute('x2', round($end_x)); $line->setAttribute('y2', round($end_y)); $line->setAttribute('stroke', $color); $line->setAttribute('stroke-width', $line_width); $line->setAttribute('stroke-dasharray', $dash_length . ',' . $blank_length); $this->svg->appendChild($line); } public function draw_poly_line($x_y_pair_array, $color, $line_width = 1) { foreach($x_y_pair_array as &$x_y) { $x_y = round($x_y[0]) . ',' . round($x_y[1]); } $poly_points = implode(' ', $x_y_pair_array); $polyline = $this->image->createElement('polyline'); $polyline->setAttribute('stroke', $color); $polyline->setAttribute('stroke-width', $line_width); $polyline->setAttribute('fill', 'none'); $polyline->setAttribute('points', implode(' ', $x_y_pair_array)); $this->svg->appendChild($polyline); } public function png_image_to_type($file) { return $file; } public function jpg_image_to_type($file) { return $file; } public function image_copy_merge($source_image_object, $to_x, $to_y, $source_x = 0, $source_y = 0, $width = -1, $height = -1) { $image = $this->image->createElement('image'); $image->setAttribute('x', $to_x); $image->setAttribute('y', $to_y); $image->setAttribute('width', $width); $image->setAttribute('height', $height); $image->setAttribute('xlink:href', $source_image_object); if($source_image_object instanceof pts_graph_ir_value && $source_image_object->get_attribute('href') != null) { $link = $this->image->createElement('a'); $link->setAttribute('xlink:href', $source_image_object->get_attribute('href')); $link->setAttribute('xlink:show', 'new'); $link->appendChild($image); $this->svg->appendChild($link); } else { $this->svg->appendChild($image); } } public function convert_hex_to_type($hex) { if(($short = substr($hex, 1, 3)) == substr($hex, 4, 3)) { // very basic shortening, but could do it more properly to find #XXYYZZ collapsing to #XYZ $hex = '#' . $short; } return $hex; } public function convert_type_to_hex($type) { if(strlen($type) == 4) { $type .= substr($type, 1); } return $type; } public function text_string_dimensions($string, $font_type, $font_size, $predefined_string = false) { return array(0, 0); // TODO: implement, though seems to do fine without it for the SVG renderer } } ?> phoronix-test-suite/pts-core/objects/bilde_renderer/bilde_gd_renderer.php0000644000175000017500000002017011626461304027103 0ustar michaelmichael. */ abstract class bilde_gd_renderer extends bilde_renderer { public function __construct($width, $height, $embed_identifiers = null) { $this->image = $this->init_new_gd_image($width, $height); $this->image_width = $width; $this->image_height = $height; } public static function renderer_supported() { return extension_loaded('gd') && function_exists('imagettftext') && self::find_default_ttf_font(); } public function html_embed_code($file_name, $attributes = null, $is_xsl = false) { $file_name = str_replace('BILDE_EXTENSION', strtolower($this->get_renderer()), $file_name); $attributes = pts_arrays::to_array($attributes); $attributes['src'] = $file_name; if($is_xsl) { $html = ''; foreach($attributes as $option => $value) { $html .= '' . $value . ''; } $html .= ''; } else { $html = ' $value) { $html .= $option . '="' . $value . '" '; } $html .= '/>'; } return $html; } /* public function render_image($output_file = null, $quality = 100) { // To be implemented by the class extending bilde_gd_renderer } */ public function resize_image($width, $height) { $img = $this->image; $this->image = $this->init_new_gd_image($width, $height); $this->image_width = $width; $this->image_height = $height; $this->image_copy_merge($img, 0, 0); } public function destroy_image() { imagedestroy($this->image); } public function write_text_left($text_string, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text = false) { $text_dimensions = $this->text_string_dimensions($text_string, $font_type, $font_size); $text_width = $text_dimensions[0]; $text_height = $text_dimensions[1]; if($rotate_text == false) { $text_x = $bound_x1; $text_y = $bound_y1 + round($text_height / 2); $rotation = 0; } else { $text_x = $bound_x1 - round($text_height / 4); $text_y = $bound_y1 + round($text_height / 2); $rotation = 270; } imagettftext($this->image, $font_size, $rotation, $text_x, $text_y, $font_color, $font_type, $text_string); } public function write_text_right($text_string, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text = false) { $text_dimensions = $this->text_string_dimensions($text_string, $font_type, $font_size); $text_width = $text_dimensions[0]; $text_height = $text_dimensions[1]; $text_x = $bound_x2 - $text_width; $text_y = $bound_y1 + round($text_height / 2); if($rotate_text) { $rotation = 90; $text_x += $text_width; } else { $rotation = 0; } imagettftext($this->image, $font_size, $rotation, $text_x, $text_y, $font_color, $font_type, $text_string); } public function draw_arc($center_x, $center_y, $radius, $offset_percent, $percent, $body_color, $border_color = null, $border_width = 1, $title = null) { imagefilledarc($this->image, $center_x, $center_y, ($radius * 2), ($radius * 2), ($offset_percent * 360), ($percent * 360), $body_color, IMG_ARC_PIE); } public function write_text_center($text_string, $font_type, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text = false) { if($bound_x1 != $bound_x2) { while($this->text_string_width($text_string, $font_type, $font_size) > abs($bound_x2 - $bound_x1 - 2)) { $font_size -= 0.5; } } $text_dimensions = $this->text_string_dimensions(strtoupper($text_string), $font_type, $font_size); $text_height = $text_dimensions[1]; $text_dimensions = $this->text_string_dimensions($text_string, $font_type, $font_size); $text_width = $text_dimensions[0]; if($rotate_text == false) { $rotation = 0; $text_x = (($bound_x2 - $bound_x1) / 2) + $bound_x1 - round($text_width / 2); $text_y = $bound_y1 + $text_height; } else { $rotation = 90; $text_x = $bound_x1 + $text_height; $text_y = (($bound_y2 - $bound_y1) / 2) + $bound_y1 + round($text_width / 2); } imagettftext($this->image, $font_size, $rotation, $text_x, $text_y, $font_color, $font_type, $text_string); } public function draw_rectangle($x1, $y1, $width, $height, $background_color) { imagefilledrectangle($this->image, $x1, $y1, $width, $height, $background_color); } public function draw_rectangle_border($x1, $y1, $width, $height, $border_color) { imagerectangle($this->image, $x1, $y1, $width, $height, $border_color); } public function draw_polygon($points, $body_color, $border_color = null, $border_width = 0) { if(isset($points[0]) && is_array($points[0]) && count($points[0]) >= 2) { $points_r = array(); foreach($points as $point_set) { foreach(array_slice($point_set, 0, 2) as $point) { array_push($points_r, $point); } } $points = $points_r; } $num_points = floor(count($points) / 2); imagefilledpolygon($this->image, $points, $num_points, $body_color); if($border_width > 0 && !empty($border_color)) { // TODO: implement $border_width imagepolygon($this->image, $points, $num_points, $border_color); } } public function draw_ellipse($center_x, $center_y, $width, $height, $body_color, $border_color = null, $border_width = 0, $default_hide = false) { if($default_hide == true) { return false; } imagefilledellipse($this->image, $center_x, $center_y, $width, $height, $body_color); if($border_width > 0 && !empty($border_color)) { // TODO: implement $border_width imageellipse($this->image, $center_x, $center_y, $width, $height, $border_color); } } public function draw_line($start_x, $start_y, $end_x, $end_y, $color, $line_width = 1, $title = null) { for($i = 0; $i < $line_width; $i++) { if($start_x == $end_x) { imageline($this->image, $start_x + $i, $start_y, $end_x + $i, $end_y, $color); } else { imageline($this->image, $start_x, $start_y + $i, $end_x, $end_y + $i, $color); } } } public function png_image_to_type($file) { return imagecreatefrompng($file); } public function jpg_image_to_type($file) { return imagecreatefromjpeg($file); } public function image_copy_merge($source_image_object, $to_x, $to_y, $source_x = 0, $source_y = 0, $width = -1, $height = -1) { if($width == -1) { $width = imagesx($source_image_object); } if($height == -1) { $height = imagesy($source_image_object); } imagecopyresampled($this->image, $source_image_object->get_value(), $to_x, $to_y, $source_x, $source_y, $width, $height, $width, $height); } public function convert_hex_to_type($hex) { return imagecolorallocate($this->image, hexdec(substr($hex, 1, 2)), hexdec(substr($hex, 3, 2)), hexdec(substr($hex, 5, 2))); } public function convert_type_to_hex($type) { return '#' . str_pad(base_convert($type, 10, 16), 6, 0, STR_PAD_LEFT); } public function text_string_dimensions($string, $font_type, $font_size, $predefined_string = false) { return $this->soft_text_string_dimensions($string, $font_type, $font_size, $predefined_string); } // Privates / Protected protected function init_new_gd_image($width, $height) { $img = imagecreatetruecolor($width, $height); imageinterlace($img, true); if(function_exists('imageantialias')) { imageantialias($img, true); } return $img; } } ?> phoronix-test-suite/pts-core/objects/client/pts_phoroscript_interpreter.php0000644000175000017500000002404412120141002027642 0ustar michaelmichael. */ class pts_phoroscript_interpreter { private $script_file; private $environmental_variables; private $var_current_directory; public function __construct($script, $env_vars = null, $set_current_path = null) { if(!isset($env_vars['HOME'])) { $env_vars['HOME'] = $set_current_path; } $this->environmental_variables = ($env_vars == null ? pts_client::environmental_variables() : array_merge(pts_client::environmental_variables(), $env_vars)); $this->script_file = is_file($script) ? $script : null; $this->var_current_directory = $set_current_path; } protected function get_real_path($path, &$pass_arguments = null) { if($path == "\$LOG_FILE") { return $this->environmental_variables["LOG_FILE"]; } $this->parse_variables_in_string($path, $pass_arguments); if(substr($path, 0, 1) == '~') { $path = $this->environmental_variables["HOME"] . substr($path, 2); } if(strpos($path, '*') !== false) { $grep_dir = pts_strings::add_trailing_slash(str_replace('"', null, $this->var_current_directory)); // needed for phodevi::is_windows() specviewperf10 $glob = pts_file_io::glob($grep_dir . $path); return count($glob) > 0 ? array_shift($glob) : $this->var_current_directory; } else if(is_file($path)) { return $path; } else if(is_file($this->var_current_directory . $path)) { return $this->var_current_directory . $path; } else { return pts_strings::add_trailing_slash($this->var_current_directory . $path); } } protected function find_file_in_array(&$string_array) { $found_file = false; foreach($string_array as $segment) { if(is_file($segment)) { $found_file = $segment; break; } else if(is_file($this->var_current_directory . $segment)) { $found_file = $this->var_current_directory . $segment; break; } } return $found_file; } protected function parse_variables_in_string(&$to_parse, &$pass_arguments) { $pass_arguments_r = pts_strings::trim_explode(' ', $pass_arguments); $offset = -1; while(($offset = strpos($to_parse, '$', ($offset + 1))) !== false) { if($to_parse[($offset - 1)] == "\\") { continue; } $var = substr($to_parse, $offset + 1); foreach(array("\n", ' ', '-', '.', "\"", '\\', "'") as $token) { $this_str = strtok($var, $token); if($this_str !== false) { $var = $this_str; } } if($var == null) { continue; } $before_var = substr($to_parse, 0, $offset); $after_var = substr($to_parse, $offset + 1 + strlen($var)); $var_value = null; if($var == '@') { $var_value = $pass_arguments; } if(isset($this->environmental_variables[$var])) { $var_value = $this->environmental_variables[$var]; } else if(is_numeric($var) && isset($pass_arguments_r[($var - 1)])) { $var_value = $pass_arguments_r[($var - 1)]; } /* // Stefan reports that this is not needed... if(phodevi::is_windows() && $var == "LOG_FILE") { $value = str_replace('/', '\\', $value); } */ $to_parse = $before_var . $var_value . $after_var; } } public function execute_script($pass_arguments = null) { if($this->script_file == null) { return false; } $script_contents = file_get_contents($this->script_file); $prev_exit_status = 0; $script_pointer = -1; do { $exit_status = 0; if($prev_exit_status != 0) { $exit_status = $prev_exit_status; $prev_exit_status = 0; } $script_contents = substr($script_contents, ($script_pointer + 1)); $line = $script_contents; $prev_script_pointer = $script_pointer; if(($script_pointer = strpos($line, "\n")) !== false) { $line = substr($line, 0, $script_pointer); } $line_r = $line != null ? pts_strings::trim_explode(' ', $line) : null; switch((isset($line_r[0]) ? $line_r[0] : null)) { case '': break; case 'mv': // TODO: implement folder support better $line_r[1] = $this->get_real_path($line_r[1], $pass_arguments); $line_r[2] = $this->get_real_path($line_r[2], $pass_arguments); //pts_file_io::delete($line_r[2], null, true); //copy($line_r[1], $line_r[2] . (is_dir($line_r[2]) ? basename($line_r[1]) : null)); //pts_file_io::delete($line_r[1], null, true); rename($line_r[1], $line_r[2] . (is_dir($line_r[2]) ? basename($line_r[1]) : null)); break; case 'cp': // TODO: implement folder support better $line_r[1] = $this->get_real_path($line_r[1], $pass_arguments); $line_r[2] = $this->get_real_path($line_r[2], $pass_arguments); copy($line_r[1], $line_r[2] . (is_dir($line_r[2]) ? basename($line_r[1]) : null)); break; case 'cat': // TODO: implement folder support better $line_r[1] = $this->get_real_path($line_r[1], $pass_arguments); $line_r[3] = $this->get_real_path($line_r[3], $pass_arguments); copy($line_r[1], $line_r[3]); break; case 'cd': if($line_r[1] == '..') { if(substr($this->var_current_directory, -1) == '/') { $this->var_current_directory = substr($this->var_current_directory, 0, -1); } $this->var_current_directory = substr($this->var_current_directory, 0, strrpos($this->var_current_directory, '/') + 1); } else if($line_r[1] == '~') { $this->var_current_directory = $this->environmental_variables["HOME"]; } else if(substr($line_r[1], 0, 1) == '"') { // On Windows some directories are encased in quotes for spaces in the directory names array_shift($line_r); $this->var_current_directory = implode(' ', $line_r); } else if(is_readable($line_r[1])) { $this->var_current_directory = $line_r[1]; } else if(is_readable($this->get_real_path($line_r[1], $pass_arguments))) { $this->var_current_directory = $this->get_real_path($line_r[1], $pass_arguments); } break; case 'touch': if(!is_file($this->var_current_directory . $line_r[1]) && is_writable($this->var_current_directory)) { touch($this->var_current_directory . $line_r[1]); } break; case 'mkdir': pts_file_io::mkdir($this->var_current_directory . $line_r[1]); break; case 'rm': for($i = 1; $i < count($line_r); $i++) { if(is_file($this->var_current_directory . $line_r[$i])) { unlink($this->var_current_directory . $line_r[$i]); } else if(is_dir($this->var_current_directory . $line_r[$i])) { pts_file_io::delete($this->var_current_directory . $line_r[$i], null, true); } } break; case 'chmod': $chmod_file = self::find_file_in_array($line_r); if($chmod_file) { chmod($chmod_file, 0755); } break; case 'unzip': $zip_file = self::find_file_in_array($line_r); pts_compression::zip_archive_extract($zip_file, $this->var_current_directory); break; case 'tar': // TODO: implement break; case 'echo': if($line == "echo $? > ~/install-exit-status") { file_put_contents($this->var_current_directory . "install-exit-status", $exit_status); break; } else if($line == "echo $? > ~/test-exit-status") { file_put_contents($this->var_current_directory . "test-exit-status", $exit_status); break; } $start_echo = strpos($script_contents, "\"") + 1; $end_echo = $start_echo - 1; do { $end_echo = strpos($script_contents, "\"", $end_echo + 1); } while($script_contents[($end_echo - 1)] == "\\"); $script_pointer = strpos($script_contents, "\n", $end_echo); $line_remainder = substr($script_contents, ($end_echo + 1), ($script_pointer - $end_echo - 1)); $echo_contents = substr($script_contents, $start_echo, ($end_echo - $start_echo)); $this->parse_variables_in_string($echo_contents, $pass_arguments); $echo_contents = str_replace("\\$", "\$", $echo_contents); $echo_contents = str_replace("\\\"", "\"", $echo_contents); if(($to_file = strpos($line_remainder, ' > ')) !== false) { $to_file = trim(substr($line_remainder, $to_file + 3)); if(($end_file = strpos($to_file, ' ')) !== false) { $to_file = substr($to_file, 0, $end_file); } // TODO: right now it's expecting the file location pipe to be relative location $echo_dir = pts_strings::add_trailing_slash(str_replace('"', null, $this->var_current_directory)); // needed for phodevi::is_windows() specviewperf10 file_put_contents($echo_dir . $to_file, $echo_contents . "\n"); } else { echo $echo_contents; } break; case '#!/bin/sh': case '#': case null: // IGNORE break; case 'case': //echo "\nUNHANDLED EVENT\n"; return false; // TODO: decide how to handle break; default: $exec_output = array(); if(phodevi::is_windows() && substr($line, 0, 2) == "./") { $line = substr($line, 2); } $this->parse_variables_in_string($line, $pass_arguments); $cd_dir = $this->var_current_directory; if(phodevi::is_windows() && strpos($cd_dir, ':\\') === 1) { $cd_dir = str_replace('/', '\\', $cd_dir); $cd_dir = str_replace('\\\\', '\\', $cd_dir); } exec("cd " . $cd_dir . " && " . $line . " 2>&1", $exec_output, $prev_exit_status); break; } } while($script_contents != false); } } ?> phoronix-test-suite/pts-core/objects/client/pts_openbenchmarking_client.php0000644000175000017500000002712212202502346027530 0ustar michaelmichael. */ class pts_openbenchmarking_client { private static $openbenchmarking_account = false; private static $client_settings = null; public static function upload_test_result(&$object) { if($object instanceof pts_test_run_manager) { $result_file = new pts_result_file($object->get_file_name()); $local_file_name = $object->get_file_name(); $results_identifier = $object->get_results_identifier(); } else if($object instanceof pts_result_file) { $result_file = &$object; $local_file_name = $result_file->get_identifier(); $results_identifier = null; } // Validate the XML // Rely upon server-side validation in case of additions to the spec later on as might be a problem with the JSON addition /* if($result_file->xml_parser->validate() == false) { echo PHP_EOL . 'Errors occurred parsing the result file XML.' . PHP_EOL; return false; } */ // Ensure the results can be shared if(self::result_upload_supported($result_file) == false) { return false; } if(pts_network::network_support_available() == false) { echo PHP_EOL . 'No network support available.' . PHP_EOL; return false; } $composite_xml = $result_file->xml_parser->getXML(); $system_log_dir = PTS_SAVE_RESULTS_PATH . $result_file->get_identifier() . '/system-logs/'; if(pts_config::read_bool_config('PhoronixTestSuite/Options/OpenBenchmarking/AlwaysUploadSystemLogs', 'FALSE')) { $upload_system_logs = true; } else if(isset(self::$client_settings['UploadSystemLogsByDefault'])) { $upload_system_logs = self::$client_settings['UploadSystemLogsByDefault']; } else if(is_dir($system_log_dir)) { $upload_system_logs = pts_user_io::prompt_bool_input('Would you like to attach the system logs (lspci, dmesg, lsusb, etc) to the test result', true, 'UPLOAD_SYSTEM_LOGS'); } $system_logs = null; $system_logs_hash = null; if(is_dir($system_log_dir) && $upload_system_logs) { $is_valid_log = true; $finfo = function_exists('finfo_open') ? finfo_open(FILEINFO_MIME_TYPE) : false; foreach(pts_file_io::glob($system_log_dir . '*') as $log_dir) { if($is_valid_log == false || !is_dir($log_dir)) { $is_valid_log = false; break; } foreach(pts_file_io::glob($log_dir . '/*') as $log_file) { if(!is_file($log_file)) { $is_valid_log = false; break; } if($finfo && substr(finfo_file($finfo, $log_file), 0, 5) != 'text/') { $is_valid_log = false; break; } } } if($is_valid_log) { $system_logs_zip = pts_client::create_temporary_file(); pts_compression::zip_archive_create($system_logs_zip, $system_log_dir); if(filesize($system_logs_zip) < 2097152) { // If it's over 2MB, probably too big $system_logs = base64_encode(file_get_contents($system_logs_zip)); $system_logs_hash = sha1($system_logs); } else { trigger_error('The systems log attachment is too large to upload to OpenBenchmarking.org.', E_USER_WARNING); } unlink($system_logs_zip); } } $to_post = array( 'composite_xml' => base64_encode($composite_xml), 'composite_xml_hash' => sha1($composite_xml), 'local_file_name' => $local_file_name, 'this_results_identifier' => $results_identifier, 'system_logs_zip' => $system_logs, 'system_logs_hash' => $system_logs_hash ); if(isset(self::$client_settings['ResultUploadsDefaultDisplayStatus']) && is_numeric(self::$client_settings['ResultUploadsDefaultDisplayStatus'])) { $to_post['display_status'] = self::$client_settings['ResultUploadsDefaultDisplayStatus']; } $json_response = pts_openbenchmarking::make_openbenchmarking_request('upload_test_result', $to_post); $json_response = json_decode($json_response, true); if(!is_array($json_response)) { trigger_error('Unhandled Exception', E_USER_ERROR); return false; } if(isset($json_response['openbenchmarking']['upload']['error'])) { trigger_error($json_response['openbenchmarking']['upload']['error'], E_USER_ERROR); } if(isset($json_response['openbenchmarking']['upload']['url'])) { echo PHP_EOL . 'Results Uploaded To: ' . $json_response['openbenchmarking']['upload']['url'] . PHP_EOL; pts_module_manager::module_process('__event_openbenchmarking_upload', $json_response); } //$json['openbenchmarking']['upload']['id'] if(isset(self::$client_settings['RemoveLocalResultsOnUpload']) && self::$client_settings['RemoveLocalResultsOnUpload'] && $local_file_name != null) { pts_client::remove_saved_result_file($local_file_name); } return isset($json_response['openbenchmarking']['upload']['url']) ? $json_response['openbenchmarking']['upload']['url'] : false; } public static function init_account($openbenchmarking) { if(isset($openbenchmarking['user_name']) && isset($openbenchmarking['communication_id']) && isset($openbenchmarking['sav'])) { if(IS_FIRST_RUN_TODAY) { // Might as well make sure OpenBenchmarking.org account has the latest system info // But don't do it everytime to preserve bandwidth $openbenchmarking['s_s'] = base64_encode(phodevi::system_software(true)); $openbenchmarking['s_h'] = base64_encode(phodevi::system_hardware(true)); } $return_state = pts_openbenchmarking::make_openbenchmarking_request('account_verify', $openbenchmarking); $json = json_decode($return_state, true); if(isset($json['openbenchmarking']['account']['valid'])) { // The account is valid self::$openbenchmarking_account = $openbenchmarking; self::$client_settings = $json['openbenchmarking']['account']['settings']; } } } public static function get_openbenchmarking_account() { return self::$openbenchmarking_account; } public static function auto_upload_results() { return isset(self::$client_settings['AutoUploadResults']) && self::$client_settings['AutoUploadResults']; } public static function override_client_setting($key, $value) { self::$client_settings[$key] = $value; } protected static function result_upload_supported(&$result_file) { foreach($result_file->get_result_objects() as $result_object) { $test_profile = new pts_test_profile($result_object->test_profile->get_identifier()); if($test_profile->allow_results_sharing() == false) { echo PHP_EOL . $result_object->test_profile->get_identifier() . ' does not allow test results to be uploaded.' . PHP_EOL . PHP_EOL; return false; } } return true; } public static function fetch_repository_changelog($repo_name) { $index_file = PTS_OPENBENCHMARKING_SCRATCH_PATH . $repo_name . '.changes'; if(!is_file($index_file) || filemtime($index_file) < (time() - 86400)) { // Refresh the repository change-log just once a day should be fine $server_index = pts_openbenchmarking::make_openbenchmarking_request('repo_changes', array('repo' => $repo_name)); if(json_decode($server_index) != false) { file_put_contents($index_file, $server_index); } } return is_file($index_file) ? json_decode(file_get_contents($index_file), true) : false; } public static function user_name() { return isset(self::$openbenchmarking_account['user_name']) ? self::$openbenchmarking_account['user_name'] : false; } public static function upload_usage_data($task, $data) { switch($task) { case 'test_install': list($test_install, $time_elapsed) = $data; $upload_data = array('test_identifier' => $test_install->test_profile->get_identifier(), 'test_version' => $test_install->test_profile->get_test_profile_version(), 'elapsed_time' => $time_elapsed); pts_network::http_upload_via_post(pts_openbenchmarking::openbenchmarking_host() . 'extern/statistics/report-test-install.php', $upload_data); break; case 'test_complete': list($test_result, $time_elapsed) = $data; $upload_data = array('test_identifier' => $test_result->test_profile->get_identifier(), 'test_version' => $test_result->test_profile->get_test_profile_version(), 'elapsed_time' => $time_elapsed); pts_network::http_upload_via_post(pts_openbenchmarking::openbenchmarking_host() . 'extern/statistics/report-test-completion.php', $upload_data); break; case 'test_install_failure': list($test_install, $error) = $data; $upload_data = array('test_identifier' => $test_install->test_profile->get_identifier(), 'error' => $error, 'os' => phodevi::read_property('system', 'vendor-identifier')); pts_network::http_upload_via_post(pts_openbenchmarking::openbenchmarking_host() . 'extern/statistics/report-test-install-failure.php', $upload_data); break; } } public static function upload_hwsw_data($to_report) { if(!defined('PTS_GSID')) { return false; } foreach($to_report as $component => &$value) { if(empty($value)) { unset($to_report[$component]); continue; } $value = $component . '=' . $value; } $upload_data = array('report_hwsw' => implode(';', $to_report), 'gsid' => PTS_GSID); pts_network::http_upload_via_post(pts_openbenchmarking::openbenchmarking_host() . 'extern/statistics/report-installed-hardware-software.php', $upload_data); } public static function upload_pci_data($to_report) { if(!defined('PTS_GSID')) { return false; } if(!is_array($to_report)) { return false; } $to_report = base64_encode(serialize($to_report)); $upload_data = array('report_pci_data' => $to_report, 'gsid' => PTS_GSID); pts_network::http_upload_via_post(pts_openbenchmarking::openbenchmarking_host() . 'extern/statistics/report-pci-data.php', $upload_data); } public static function upload_usb_data($to_report) { if(!defined('PTS_GSID')) { return false; } if(!is_array($to_report)) { return false; } $to_report = base64_encode(serialize($to_report)); $upload_data = array('report_usb_data' => $to_report, 'gsid' => PTS_GSID); pts_network::http_upload_via_post(pts_openbenchmarking::openbenchmarking_host() . 'extern/statistics/report-usb-data.php', $upload_data); } public static function request_gsid() { $payload = array( 'client_version' => PTS_VERSION, 'client_os' => phodevi::read_property('system', 'vendor-identifier') ); $json = pts_openbenchmarking::make_openbenchmarking_request('request_gsid', $payload); $json = json_decode($json, true); return isset($json['openbenchmarking']['gsid']) ? $json['openbenchmarking']['gsid'] : false; } public static function update_gsid() { $payload = array( 'client_version' => PTS_VERSION, 'client_os' => phodevi::read_property('system', 'vendor-identifier') ); pts_openbenchmarking::make_openbenchmarking_request('update_gsid', $payload); } public static function retrieve_gsid() { // If the GSID_E and GSID_P are not known due to being from an old client $json = pts_openbenchmarking::make_openbenchmarking_request('retrieve_gsid', array()); $json = json_decode($json, true); return isset($json['openbenchmarking']['gsid']) ? $json['openbenchmarking']['gsid'] : false; } } ?> phoronix-test-suite/pts-core/objects/client/pts_test_notes_manager.php0000644000175000017500000001073412102045500026533 0ustar michaelmichael. */ class pts_test_notes_manager { private static $notes = array(); public static function add_note($note) { $note = trim($note); if(!empty($note) && !in_array($note, self::$notes)) { array_push(self::$notes, $note); } } public static function generate_test_notes(&$test_result_objects) { // TODO XXX: Integrate with system table notes static $check_processes = null; $test_types = array(); $test_tags = array(); foreach($test_result_objects as $test_result) { pts_arrays::unique_push($test_types, $test_result->test_profile->get_test_hardware_type()); foreach($test_result->test_profile->get_internal_tags() as $tag) { pts_arrays::unique_push($test_tags, $tag); } } if(in_array('Java', $test_tags)) { self::add_note(phodevi::read_property('system', 'java-version')); } if(in_array('Python', $test_tags)) { self::add_note(phodevi::read_property('system', 'python-version')); } if(in_array('Wine', $test_tags)) { self::add_note(phodevi::read_property('system', 'wine-version')); } if(in_array('OpenCL', $test_tags)) { $cores = phodevi::read_property('gpu', 'compute-cores'); if($cores > 0) { self::add_note('GPU Compute Cores: ' . $cores); } } /* if(phodevi::is_bsd() == false) { if(empty($check_processes)) { $check_processes = array( 'Compiz' => array('compiz', 'compiz.real'), 'Firefox' => array('firefox', 'mozilla-firefox', 'mozilla-firefox-bin'), 'Thunderbird' => array('thunderbird', 'mozilla-thunderbird', 'thunderbird-bin'), 'BOINC' => array('boinc', 'boinc_client') ); } self::add_note(self::process_running_string($check_processes)); } */ // Check if Security Enhanced Linux was enforcing, permissive, or disabled if(is_readable('/etc/sysconfig/selinux')) { if(stripos(file_get_contents('/etc/sysconfig/selinux'), 'selinux=disabled') === false) { self::add_note('SELinux: Enabled'); } } else if(isset(phodevi::$vfs->cmdline)) { if(stripos(phodevi::$vfs->cmdline, 'selinux=1') != false) { self::add_note('SELinux: Enabled'); } } /* // Encrypted file-system? if(phodevi::is_linux() && is_readable('/sys/fs/ecryptfs/version')) { self::add_note('eCryptfs was active.'); } */ self::add_note(phodevi::read_property('motherboard', 'power-mode')); if(in_array('Graphics', $test_types) || in_array('System', $test_types)) { $aa_level = phodevi::read_property('gpu', 'aa-level'); $af_level = phodevi::read_property('gpu', 'af-level'); if(!empty($aa_level)) { self::add_note('Antialiasing: ' . $aa_level); } if(!empty($af_level)) { self::add_note('Anisotropic Filtering: ' . $af_level); } } $notes_string = trim(implode('. ', self::$notes)); if($notes_string != null) { $notes_string .= '.'; } self::$notes = array(); return $notes_string; } public static function process_running_string($process_arr) { // Format a nice string that shows processes running $p = array(); $p_string = null; $process_arr = pts_arrays::to_array($process_arr); foreach($process_arr as $p_name => $p_processes) { foreach($p_processes as $process) { if(pts_client::is_process_running($process)) { array_push($p, $p_name); } } } $p = array_keys(array_flip($p)); if(($p_count = count($p)) > 0) { for($i = 0; $i < $p_count; $i++) { $p_string .= $p[$i]; if($i != ($p_count - 1) && $p_count > 2) { $p_string .= ','; } $p_string .= ' '; if($i == ($p_count - 2)) { $p_string .= 'and '; } } $p_string .= $p_count == 1 ? 'was' : 'were'; $p_string .= ' running on this system'; } return $p_string; } } ?> phoronix-test-suite/pts-core/objects/client/pts_test_file_download.php0000644000175000017500000000715712172340153026535 0ustar michaelmichael. */ class pts_test_file_download { static $longest_file_name = null; static $longest_file_name_length = 0; private $url; private $filename; private $filesize; private $md5; private $sha256; private $architecture; private $platform; private $download_location_type = null; private $download_location_path = null; public function __construct($url = null, $filename = null, $filesize = 0, $md5 = null, $sha256 = null, $platform = null, $architecture = null) { $this->filename = empty($filename) ? basename($url) : $filename; $this->url = $this->filename == $url ? null : $url; $this->filesize = !is_numeric($filesize) ? 0 : $filesize; $this->md5 = $md5; $this->sha256 = $sha256; $this->location_type = null; $this->location_path = array(); $this->platform = $platform; $this->architecture = $architecture; // Check for longest file name length as the text UI takes advantage of it if(strlen($this->filename) > self::$longest_file_name_length) { self::$longest_file_name = $this->filename; self::$longest_file_name_length = strlen($this->filename); } } public function get_download_url_array() { return pts_strings::comma_explode($this->url); } public function get_download_url_string() { return $this->url; } public function get_platform_array() { return pts_strings::comma_explode($this->platform); } public function get_platform_string() { return $this->platform; } public function get_architecture_array() { return pts_strings::comma_explode($this->architecture); } public function get_architecture_string() { return $this->architecture; } public function get_filename() { return $this->filename; } public function get_filesize() { return $this->filesize; } public function get_md5() { return $this->md5; } public function get_sha256() { return $this->sha256; } public function check_file_hash($file) { if($this->sha256) { return hash_file('sha256', $file) == $this->sha256; } else if($this->md5) { return md5_file($file) == $this->md5; } else { return true; } } public function set_filesize($size) { $this->filesize = is_numeric($size) ? $size : 0; } public function set_download_location($location_type, $location_path = array()) { // IN_DESTINATION_DIR == already good, in the destination directory already, was previously downloaded // LOCAL_DOWNLOAD_CACHE == In a local download cache, can be copied, etc // REMOTE_DOWNLOAD_CACHE == In a remote download cache for download // LOOKASIDE_DOWNLOAD_CACHE == In another test installation directory $this->download_location_type = $location_type; $this->download_location_path = $location_path; } public function get_download_location_type() { return $this->download_location_type; } public function get_download_location_path() { return $this->download_location_path; } } ?> phoronix-test-suite/pts-core/objects/client/pts_test_install_request.php0000644000175000017500000001765412222310114027136 0ustar michaelmichael. */ class pts_test_install_request { public $test_profile; private $test_files; public $install_time_duration = -1; public $compiler_mask_dir = false; public $install_error = null; public $special_environment_vars; public function __construct($test) { if($test instanceof pts_test_profile) { $this->test_profile = $test; } else { $this->test_profile = new pts_test_profile($test); } $this->test_files = array(); $this->special_environment_vars = array(); } public static function read_download_object_list($test, $do_file_checks = true) { // A way to get just the download object list if needed $test_install_request = new pts_test_install_request($test); $test_install_request->generate_download_object_list($do_file_checks); return $test_install_request->get_download_objects(); } public function __toString() { return $this->test_profile->get_identifier(); } public function get_download_objects() { return $this->test_files; } public function get_download_object_count() { return count($this->test_files); } public function generate_download_object_list($do_file_checks = true) { $download_xml_file = $this->test_profile->get_file_download_spec(); if($download_xml_file != null) { $xml_parser = new pts_test_downloads_nye_XmlReader($download_xml_file); $package_url = $xml_parser->getXMLArrayValues('PhoronixTestSuite/Downloads/Package/URL'); $package_md5 = $xml_parser->getXMLArrayValues('PhoronixTestSuite/Downloads/Package/MD5'); $package_sha256 = $xml_parser->getXMLArrayValues('PhoronixTestSuite/Downloads/Package/SHA256'); $package_filename = $xml_parser->getXMLArrayValues('PhoronixTestSuite/Downloads/Package/FileName'); $package_filesize = $xml_parser->getXMLArrayValues('PhoronixTestSuite/Downloads/Package/FileSize'); $package_platform = $xml_parser->getXMLArrayValues('PhoronixTestSuite/Downloads/Package/PlatformSpecific'); $package_architecture = $xml_parser->getXMLArrayValues('PhoronixTestSuite/Downloads/Package/ArchitectureSpecific'); foreach(array_keys($package_url) as $i) { if(!empty($package_platform[$i]) && $do_file_checks) { $platforms = pts_strings::comma_explode($package_platform[$i]); if(!in_array(phodevi::operating_system(), $platforms) && !(phodevi::is_bsd() && in_array('Linux', $platforms) && (pts_client::executable_in_path('kldstat') && strpos(shell_exec('kldstat -n linux 2>&1'), 'linux.ko') != false))) { // This download does not match the operating system continue; } } if(!empty($package_architecture[$i]) && $do_file_checks) { $architectures = pts_strings::comma_explode($package_architecture[$i]); if(phodevi::cpu_arch_compatible($architectures) == false) { // This download does not match the CPU architecture continue; } } array_push($this->test_files, new pts_test_file_download($package_url[$i], $package_filename[$i], $package_filesize[$i], $package_md5[$i], $package_sha256[$i], $package_platform[$i], $package_architecture[$i])); } } } public static function test_files_available_locally(&$test_profile) { $install_request = new pts_test_install_request($test_profile); $remote_files = pts_test_install_manager::remote_files_available_in_download_caches(); $local_download_caches = pts_test_install_manager::local_download_caches(); $remote_download_caches = pts_test_install_manager::remote_download_caches(); $install_request->generate_download_object_list(); $install_request->scan_download_caches($local_download_caches, $remote_download_caches, $remote_files); foreach($install_request->get_download_objects() as $download_object) { if($download_object->get_download_location_type() == null) { return false; } } return true; } public function scan_download_caches($local_download_caches, $remote_download_caches, $remote_files) { $download_location = $this->test_profile->get_install_dir(); $main_download_cache = pts_strings::add_trailing_slash(pts_client::parse_home_directory(pts_config::read_user_config('PhoronixTestSuite/Options/Installation/CacheDirectory', PTS_DOWNLOAD_CACHE_PATH))); foreach($this->test_files as &$download_package) { $package_filename = $download_package->get_filename(); $package_md5 = $download_package->get_md5(); $package_sha256 = $download_package->get_sha256(); if(is_file($download_location . $package_filename)) { // File is already there in the test/destination directory, must have been previously downloaded // Could add an MD5 check here to ensure validity, but if it made it here it was already valid unless user modified it if($download_package->get_filesize() == 0) { $download_package->set_filesize(filesize($download_location . $package_filename)); } $download_package->set_download_location('IN_DESTINATION_DIR'); } else if(is_file($main_download_cache . $package_filename)) { // In main download cache if($download_package->get_filesize() == 0) { $download_package->set_filesize(filesize($main_download_cache . $package_filename)); } $download_package->set_download_location('MAIN_DOWNLOAD_CACHE', array($main_download_cache . $package_filename)); } else { // Scan the local download caches foreach($local_download_caches as &$cache_directory) { if(pts_test_installer::validate_sha256_download_file($cache_directory . $package_filename, $package_sha256) || pts_test_installer::validate_md5_download_file($cache_directory . $package_filename, $package_md5)) { if($download_package->get_filesize() == 0) { $download_package->set_filesize(filesize($cache_directory . $package_filename)); } $download_package->set_download_location('LOCAL_DOWNLOAD_CACHE', array($cache_directory . $package_filename)); break; } } // Look-aside download cache copy // Check to see if the same package name with the same package check-sum is already present in another test installation $lookaside_copy = pts_test_install_manager::file_lookaside_test_installations($package_filename, $package_md5, $package_sha256); if($lookaside_copy) { if($download_package->get_filesize() == 0) { $download_package->set_filesize(filesize($lookaside_copy)); } $download_package->set_download_location('LOOKASIDE_DOWNLOAD_CACHE', array($lookaside_copy)); } // If still not found, check remote download caches if($download_package->get_download_location_type() == null) { if(!empty($package_md5) && isset($remote_files[$package_md5])) { $download_package->set_download_location('REMOTE_DOWNLOAD_CACHE', $remote_files[$package_md5]); } else { // Check for files manually foreach($remote_download_caches as $remote_dir) { $remote_file = $remote_dir . $package_filename; $stream_context = pts_network::stream_context_create(); $file_pointer = fopen($remote_file, 'r', false, $stream_context); if($file_pointer !== false) { $download_package->set_download_location('REMOTE_DOWNLOAD_CACHE', $remote_file); break; } } } } } } } } ?> phoronix-test-suite/pts-core/objects/client/pts_download_speed_manager.php0000644000175000017500000000436411606573161027356 0ustar michaelmichael. */ class pts_download_speed_manager { private static $average_count = -1; private static $average_speed = -1; public static function update_download_speed_average($download_size, $elapsed_time) { if(self::$average_count == -1) { self::load_download_speed_averages(); } $download_speed = floor($download_size / $elapsed_time); // bytes per second if(self::$average_count > 0 && self::$average_speed > 0) { // bytes per second self::$average_speed = floor(((self::$average_speed * self::$average_count) + $download_speed) / (self::$average_count + 1)); self::$average_count++; } else { self::$average_speed = $download_speed; self::$average_count = 1; } } public static function get_average_download_speed() { if(self::$average_count == -1) { self::load_download_speed_averages(); } return self::$average_speed; } public static function save_data() { self::save_download_speed_averages(); } private static function load_download_speed_averages() { self::$average_count = pts_storage_object::read_from_file(PTS_CORE_STORAGE, 'download_average_count'); self::$average_speed = pts_storage_object::read_from_file(PTS_CORE_STORAGE, 'download_average_speed'); } private static function save_download_speed_averages() { pts_storage_object::set_in_file(PTS_CORE_STORAGE, 'download_average_count', self::$average_count); pts_storage_object::set_in_file(PTS_CORE_STORAGE, 'download_average_speed', self::$average_speed); } } ?> phoronix-test-suite/pts-core/objects/client/pts_option_interface.php0000644000175000017500000000234511657247317026231 0ustar michaelmichael. */ interface pts_option_interface { // If a class implementing this interface has a public static function argument_checks() // that returns an array of pts_argument_check options, pts-core will automatically perform the argument checks prior to running the function // public static function command_aliases() is optional // public static function invalid_command() is optional public static function run($passed_arguments_array); } ?> phoronix-test-suite/pts-core/objects/client/pts_argument_check.php0000644000175000017500000000517111754655712025660 0ustar michaelmichael. */ class pts_argument_check { private $argument_index; private $function_check; private $function_return_key; public function __construct($index, $function, $return_key = null) { $this->argument_index = $index; $this->function_check = $function; $this->function_return_key = $return_key; // set to null when you don't want it to be set } public function get_argument_index() { return $this->argument_index; } public function get_function_check() { return $this->function_check; } public function get_function_return_key() { return $this->function_return_key; } public function __toString() { if($this->get_function_check() == array('pts_types', 'is_result_file')) { $type = 'Test Result'; } else if($this->get_function_check() == array('pts_types', 'identifier_to_object')) { $type = 'Test | Suite | OpenBenchmarking.org ID | Test Result'; } else if($this->get_function_check() == array('pts_types', 'is_test_or_suite')) { $type = 'Test | Suite'; } else if($this->get_function_check() == array('pts_test_profile', 'is_test_profile')) { $type = 'Test'; } else if($this->get_function_check() == array('pts_test_suite', 'is_suite')) { $type = 'Suite'; } else if($this->get_function_check() == array('pts_openbenchmarking', 'is_openbenchmarking_result_id')) { $type = 'OpenBenchmarking ID'; } else if($this->get_function_check() == array('pts_result_file', 'is_test_result_file')) { $type = 'Test Result'; } else if($this->get_function_check() == array('pts_module', 'is_module')) { $type = 'Phoronix Test Suite Module'; } else if($this->get_function_check() == 'is_file') { $type = 'File'; } else { $type = 'Unknown Object'; } $type = '[' . $type . ']' . (($this->get_argument_index() === 'VARIABLE_LENGTH') ? ' ...' : null); return $type; } } ?> phoronix-test-suite/pts-core/objects/client/pts_documentation.php0000644000175000017500000000702411773622657025554 0ustar michaelmichael. */ class pts_documentation { public static function client_commands_aliases() { $command_aliases = array(); foreach(pts_file_io::glob(PTS_COMMAND_PATH . '*.php') as $option_php_file) { $option_php = basename($option_php_file, '.php'); include_once($option_php_file); if(method_exists($option_php, 'command_aliases')) { $this_aliases = call_user_func(array($option_php, 'command_aliases')); if(is_array($this_aliases)) { foreach($this_aliases as $alias) { $command_aliases[$alias] = $option_php; } } } } return $command_aliases; } public static function client_commands_array() { $options = array('Test Installation' => array(), 'Testing' => array(), 'Batch Testing' => array(), 'OpenBenchmarking.org' => array(), 'System' => array(), 'Information' => array(), 'Asset Creation' => array(), 'Result Management' => array(), 'Result Analytics' => array(), 'Other' => array()); foreach(pts_file_io::glob(PTS_COMMAND_PATH . '*.php') as $option_php_file) { $option_php = basename($option_php_file, '.php'); $name = str_replace('_', '-', $option_php); if(!in_array(pts_strings::first_in_string($name, '-'), array('dump', 'task'))) { include_once($option_php_file); $reflect = new ReflectionClass($option_php); $constants = $reflect->getConstants(); $doc_description = isset($constants['doc_description']) ? constant($option_php . '::doc_description') : 'No summary is available.'; $doc_section = isset($constants['doc_section']) ? constant($option_php . '::doc_section') : 'Other'; $name = isset($constants['doc_use_alias']) ? constant($option_php . '::doc_use_alias') : $name; $skip = isset($constants['doc_skip']) ? constant($option_php . '::doc_skip') : false; $doc_args = array(); if($skip) { continue; } if(method_exists($option_php, 'argument_checks')) { $doc_args = call_user_func(array($option_php, 'argument_checks')); } if(!empty($doc_section) && !isset($options[$doc_section])) { $options[$doc_section] = array(); } array_push($options[$doc_section], array($name, $doc_args, $doc_description)); } } return $options; } public static function basic_description() { return 'The Phoronix Test Suite is the most comprehensive testing and benchmarking platform available for Linux, Solaris, Mac OS X, and BSD operating systems. The Phoronix Test Suite allows for carrying out tests in a fully automated manner from test installation to execution and reporting. All tests are meant to be easily reproducible, easy-to-use, and support fully automated execution. The Phoronix Test Suite is open-source under the GNU GPLv3 license and is developed by Phoronix Media in cooperation with partners.'; } } ?> phoronix-test-suite/pts-core/objects/client/pts_module_manager.php0000644000175000017500000001714512000021505025630 0ustar michaelmichael. */ class pts_module_manager { private static $modules = array(); private static $var_storage = array(); private static $module_process = array(); private static $current_module = null; // // Module Handling // public static function load_module($module) { // Load the actual file needed that contains the module return (is_file(PTS_MODULE_PATH . $module . '.php') && include_once(PTS_MODULE_PATH . $module . '.php')) || (is_file(PTS_MODULE_LOCAL_PATH . $module . '.php') && include_once(PTS_MODULE_LOCAL_PATH . $module . '.php')); } public static function modules_environmental_variables() { $module_env_vars = array(); foreach(pts_module_manager::available_modules() as $module) { pts_module_manager::load_module($module); $vars = pts_module_manager::module_call($module, 'module_environmental_variables'); if(is_array($vars)) { foreach($vars as $var) { if(!isset($module_env_vars[$var])) { $module_env_vars[$var] = array($module); } else { array_push($module_env_vars[$var], $module); } } } } return $module_env_vars; } public static function module_call($module, $process, &$object_pass = null) { if(!class_exists($module)) { return false; } if(method_exists($module, $process)) { $module_val = call_user_func(array($module, $process), $object_pass); } else { $class_vars = get_class_vars($module); $module_val = isset($class_vars[$process]) ? $class_vars[$process] : false; if($module_val == null) { eval('$module_val = ' . $module . '::' . $process . ';'); } } return $module_val; } public static function module_process($process, &$object_pass = null, $select_modules = false) { // Run a module process on all registered modules foreach(pts_module_manager::attached_modules($process, $select_modules) as $module) { pts_module_manager::set_current_module($module); $module_response = pts_module_manager::module_call($module, $process, $object_pass); switch($module_response) { case pts_module::MODULE_UNLOAD: // Unload the PTS module pts_module_manager::detach_module($module); break; case pts_module::QUIT_PTS_CLIENT: // Stop the Phoronix Test Suite immediately pts_client::exit_client(); break; } } pts_module_manager::set_current_module(null); } public static function process_environment_variables_string_to_set($env_var_string) { if(!empty($env_var_string)) { foreach(explode(';', $env_var_string) as $ev) { list($var, $value) = pts_strings::trim_explode('=', $ev); pts_client::set_environment_variable($var, $value); pts_module_manager::var_store_add($var, $value); } pts_module_manager::detect_modules_to_load(); } } public static function run_command($module, $command, $arguments = null) { $all_options = pts_module_manager::module_call($module, 'user_commands'); if(isset($all_options[$command]) && method_exists($module, $all_options[$command])) { pts_module_manager::module_call($module, $all_options[$command], $arguments); } else { // Not a valid command, list available options for the module // or help or list_options was called $all_options = pts_module_manager::module_call($module, 'user_commands'); echo PHP_EOL . 'User commands for the ' . $module . ' module:' . PHP_EOL . PHP_EOL; foreach($all_options as $option) { echo '- ' . $module . '.' . str_replace('_', '-', $option) . PHP_EOL; } echo PHP_EOL; } } public static function attach_module($module) { if(pts_module::is_module($module) == false || in_array($module, self::$modules)) { return false; } pts_module_manager::load_module($module); array_push(self::$modules, $module); if(class_exists($module)) { foreach(get_class_methods($module) as $module_method) { if(substr($module_method, 0, 2) == '__') { if(!isset(self::$module_process[$module_method])) { self::$module_process[$module_method] = array(); } array_push(self::$module_process[$module_method], $module); } } } if(defined('PTS_STARTUP_TASK_PERFORMED')) { $pass_by_ref_null = null; pts_module_manager::module_process('__startup', $pass_by_ref_null, $module); } } public static function detach_module($module) { if(self::is_module_attached($module)) { unset(self::$modules[$module]); } } public static function attached_modules($process_name = null, $select_modules = false) { if($process_name == null) { $attached = self::$modules; } else if(isset(self::$module_process[$process_name])) { $attached = self::$module_process[$process_name]; } else { $attached = array(); } if($select_modules != false) { $all_attached = $attached; $attached = array(); foreach(pts_arrays::to_array($select_modules) as $check_module) { if(in_array($check_module, $all_attached)) { array_push($attached, $check_module); } } } return $attached; } public static function is_module_attached($module) { return isset(self::$modules[$module]); } public static function available_modules($only_system_modules = false) { if($only_system_modules) { $modules = pts_file_io::glob(PTS_MODULE_PATH . '*.php'); } else { $modules = array_merge(pts_file_io::glob(PTS_MODULE_PATH . '*.php'), pts_file_io::glob(PTS_MODULE_LOCAL_PATH . '*.php')); } $module_names = array(); foreach($modules as $module) { array_push($module_names, basename($module, '.php')); } asort($module_names); return $module_names; } public static function clean_module_list() { array_unique(self::$modules); foreach(self::$modules as $i => $module) { if(pts_module::is_module($module) == false) { unset(self::$modules[$i]); } } } public static function detect_modules_to_load() { // Auto detect modules to load $env_vars = pts_storage_object::read_from_file(PTS_TEMP_STORAGE, 'environmental_variables_for_modules'); if($env_vars == false) { $env_vars = pts_module_manager::modules_environmental_variables(); } foreach($env_vars as $env_var => $modules) { if(($e = pts_client::read_env($env_var)) != false && !empty($e)) { foreach($modules as $module) { if(!pts_module_manager::is_module_attached($module)) { pts_module_manager::attach_module($module); } } } } } // // Variable Storage // public static function var_store_add($var, $value) { if(!in_array($var . '=' . $value, self::$var_storage)) { array_push(self::$var_storage, $var . '=' . $value); } } public static function var_store_string() { return implode(';', self::$var_storage); } // // Current Module // public static function set_current_module($module = null) { self::$current_module = $module; } public static function get_current_module() { return self::$current_module; } } ?> phoronix-test-suite/pts-core/objects/client/pts_installed_test.php0000644000175000017500000000545611705365100025706 0ustar michaelmichael. */ class pts_installed_test { private $xml_parser; public function __construct(&$test_profile) { $install_path = $test_profile->get_install_dir(); $read_xml = is_file($install_path . 'pts-install.xml') ? $install_path . 'pts-install.xml' : null; $this->xml_parser = new nye_XmlReader($read_xml); } public function get_install_date_time() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInstallation/History/InstallTime'); } public function get_install_date() { return substr($this->get_install_date_time(), 0, 10); } public function get_last_run_date_time() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInstallation/History/LastRunTime'); } public function get_last_run_date() { return substr($this->get_install_date_time(), 0, 10); } public function get_installed_version() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInstallation/Environment/Version'); } public function get_average_run_time() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInstallation/History/AverageRunTime'); } public function get_latest_run_time() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInstallation/History/LatestRunTime'); } public function get_latest_install_time() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInstallation/History/InstallTimeLength'); } public function get_run_count() { return ($times_run = $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInstallation/History/TimesRun')) != false ? $times_run : 0; } public function get_compiler_data() { return json_decode($this->xml_parser->getXMLValue('PhoronixTestSuite/TestInstallation/Environment/CompilerData'), true); } public function get_installed_checksum() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInstallation/Environment/CheckSum'); } public function get_installed_system_identifier() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInstallation/Environment/SystemIdentifier'); } } ?> phoronix-test-suite/pts-core/objects/client/pts_config.php0000644000175000017500000001653611733076775024160 0ustar michaelmichael. */ if(PTS_IS_CLIENT) { // Upon loading pts_client, make sure files are loaded pts_config::init_files(); } class pts_config { static $init_process_ran = false; static $xml_user_config = null; public static function init_files() { // Don't let the process run multiple times... if(pts_config::$init_process_ran) { return false; } pts_config::$init_process_ran = true; // The main PTS user client config pts_config::user_config_generate(); // Generate the graph config $json_pre = null; if(is_file(PTS_USER_PATH . 'graph-config.json')) { $json_pre = file_get_contents(PTS_USER_PATH . 'graph-config.json'); } else if(PTS_IS_CLIENT && is_file(($t = PTS_CORE_STATIC_PATH . 'graph-config-template-' . phodevi::read_property('system', 'vendor-identifier') . '.json'))) { $json_pre = file_get_contents($t); } else if(is_file(PTS_CORE_STATIC_PATH . 'graph-config-template.json')) { $json_pre = file_get_contents(PTS_CORE_STATIC_PATH . 'graph-config-template.json'); } $json_graph = array(); pts_Graph::set_default_graph_values($json_graph); if($json_pre != null) { $json_pre = json_decode($json_pre, true); if(is_array($json_pre)) { $json_graph = array_merge($json_graph, $json_pre); } } pts_Graph::init_graph_config($json_graph); file_put_contents(PTS_USER_PATH . 'graph-config.json', pts_arrays::json_encode_pretty_string($json_graph)); } public static function user_config_generate($new_config_values = null) { // Validate the config files, update them (or write them) if needed, and other configuration file tasks $read_config = new pts_config_nye_XmlReader($new_config_values); $config = new nye_XmlWriter('xsl/pts-user-config-viewer.xsl'); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/OpenBenchmarking/AnonymousUsageReporting', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/OpenBenchmarking/AnonymousSoftwareReporting', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/OpenBenchmarking/AnonymousHardwareReporting', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/OpenBenchmarking/IndexCacheTTL', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/OpenBenchmarking/AlwaysUploadSystemLogs', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/General/DefaultBrowser', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/General/UsePhodeviCache', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/General/DefaultDisplayMode', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Modules/LoadModules', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Installation/RemoveDownloadFiles', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Installation/SearchMediaForCache', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Installation/SymLinkFilesFromCache', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Installation/PromptForDownloadMirror', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Installation/EnvironmentDirectory', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Installation/CacheDirectory', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Testing/SaveSystemLogs', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Testing/SaveInstallationLogs', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Testing/SaveTestLogs', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Testing/RemoveTestInstallOnCompletion', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Testing/ResultsDirectory', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Testing/AlwaysUploadResultsToOpenBenchmarking', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Testing/AutoSortRunQueue', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/TestResultValidation/DynamicRunCount', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/TestResultValidation/LimitDynamicToTestLength', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/TestResultValidation/StandardDeviationThreshold', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/TestResultValidation/ExportResultsTo', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/BatchMode/SaveResults', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/BatchMode/OpenBrowser', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/BatchMode/UploadResults', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/BatchMode/PromptForTestIdentifier', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/BatchMode/PromptForTestDescription', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/BatchMode/PromptSaveName', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/BatchMode/RunAllTestCombinations', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/BatchMode/Configured', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Networking/NoNetworkCommunication', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Networking/Timeout', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Networking/ProxyAddress', $read_config); $config->addXmlNodeFromReader('PhoronixTestSuite/Options/Networking/ProxyPort', $read_config); $config->saveXMLFile(PTS_USER_PATH . 'user-config.xml'); } public static function bool_to_string($bool) { return $bool ? 'TRUE' : 'FALSE'; } public static function read_user_config($xml_pointer, $predefined_value = false, &$nye_xml = null) { // Generic call for reading a config file if($nye_xml instanceof nye_XmlReader) { $read_value = $nye_xml->getXmlValue($xml_pointer); } else { if(self::$xml_user_config == null) { self::$xml_user_config = new pts_config_nye_XmlReader(); } $read_value = self::$xml_user_config->getXmlValue($xml_pointer); } return !empty($read_value) ? $read_value : $predefined_value; } public static function read_bool_config($xml_pointer, $predefined_value = false, &$nye_xml = null) { $value = self::read_user_config($xml_pointer, $predefined_value, $nye_xml); return pts_strings::string_bool($value); } } ?> phoronix-test-suite/pts-core/objects/client/pts_module_option.php0000644000175000017500000001007011712463231025533 0ustar michaelmichael. */ class pts_module_option { private $option_identifier; private $option_question; private $option_supported_values; private $option_default_value; private $option_function_check; private $option_setup_check; public function __construct($identifier, $question_string, $supported_values = null, $default_value = null, $function_to_check = null, $setup_check = true) { $this->option_identifier = $identifier; $this->option_question = $question_string; $this->option_supported_values = $supported_values; $this->option_default_value = $default_value; $this->option_function_check = $function_to_check; $this->option_setup_check = $setup_check; } public function setup_check_needed() { return $this->option_setup_check; } public function get_identifier() { return $this->option_identifier; } public function get_question() { return $this->option_question; } public function get_default_value() { return $this->option_default_value; } public function get_formatted_question() { $question_string = $this->get_question(); if($this->get_default_value() != null) { $question_string .= ' [' . $this->get_default_value() . ']'; } $question_string .= ': '; return $question_string; } public function is_supported_value($input) { $supported = false; if(is_array($this->option_supported_values)) { if(in_array($input, $this->option_supported_values)) { $supported = true; } } else if(empty($input) && $this->option_default_value != null) { $supported = true; } else { switch($this->option_supported_values) { case 'NUMERIC': if(is_numeric($input)) { $supported = true; } break; case 'NUMERIC_DASH': if(!empty($input) && pts_strings::string_only_contains($input, pts_strings::CHAR_NUMERIC | pts_strings::CHAR_DASH)) { $supported = true; } break; case 'ALPHA_NUMERIC': if(!empty($input) && pts_strings::string_only_contains($input, pts_strings::CHAR_NUMERIC | pts_strings::CHAR_LETTER)) { $supported = true; } break; case 'HTTP_URL': if(substr($input, 0, 7) == 'http://') { $supported = true; } break; case 'LOCAL_DIRECTORY': if(is_dir($input)) { $supported = true; } break; case 'LOCAL_FILE': if(is_file($input)) { $supported = true; } break; case 'LOCAL_EXECUTABLE': if(is_executable($input)) { $supported = true; } break; case 'PTS_TEST_RESULT': if(pts_result_file::is_test_result_file($input)) { $supported = true; } case 'INSTALLED_TEST': if(in_array($input, pts_tests::installed_tests())) { $supported = true; } case 'VALID_SAVE_NAME': if(!empty($input) && pts_types::identifier_to_object($input) == false) { $supported = true; } case 'NOT_EMPTY': if(!empty($input)) { $supported = true; } case '': $supported = true; break; } } if($supported && !empty($this->option_function_check)) { $supported = (call_user_func($this->option_function_check, $input) == true); } return $supported; } } ?> phoronix-test-suite/pts-core/objects/client/pts_module_interface.php0000644000175000017500000001261611740152474026200 0ustar michaelmichael. */ class pts_module_interface { const module_name = "Generic Module"; const module_version = "1.0.0"; const module_description = "A description of the module."; const module_author = "Module Creator"; public static $module_store_vars = array(); public static function module_info() { } public static function module_setup() { return array(); } public static function module_setup_validate($module_options_array) { return $module_options_array; } public static function module_environmental_variables() { return array(); } public static function user_commands() { return array(); } // // The below methods are optional and can be implemented by any module // /* // // General Functions // public static function __startup($obj = null) { return; } public static function __shutdown($obj = null) { return; } // // Option Functions // public static function __pre_option_process($obj = null) { // Passed is a string containing the name of the option command about to be run return; } public static function __post_option_process($obj = null) { // Passed is a string containing the name of the option after it has run return; } // // Installation Functions // public static function __pre_install_process($obj = null) { // Passed is the pts_test_install_manager return; } public static function __pre_test_download($obj = null) { // Passed is an array where as the first element is the test identifier for the name of the test about to have its files downloaded // The second element in this array is an additional array containing the pts_test_file_download objects that will be downloaded return; } public static function __interim_test_download($obj = null) { // Passed is an array where as the first element is the test identifier for the name of the test about to have its files downloaded // The second element in this array is an additional array containing the pts_test_file_download objects that will be downloaded return; } public static function __post_test_download($obj = null) { // Passed as the first argument to this function is the test identifier for the name of the test where the file(s) were just downloaded return; } public static function __pre_test_install($obj = null) { // Passed as the first argument to this function is the test identifier for the name of the test about to be installed return; } public static function __post_test_install($obj = null) { // Passed as the first argument to this function is the test identifier for the name of the test just installed return; } public static function __post_install_process($obj = null) { // Passed is the pts_test_install_manager return; } // // Run Functions // public static function __run_manager_setup($obj = null) { // Passed is the current pts_test_run_manager return; } public static function __pre_run_process($obj = null) { // Passed is the current pts_test_run_manager, where accessible is an array of pts_test_result objects for all tests scheduled to run return; } public static function __pre_test_run($obj = null) { // Passed is a read-only copy of the current pts_test_result for the given test return; } public static function __interim_test_run($obj = null) { // Passed is a read-only copy of the current pts_test_result for the given test return; } public static function __post_test_run($obj = null) { // Passed is a read-only copy of the current pts_test_result for the given test return; } public static function __post_test_run_success($obj = null) { // Passed is a copy of the pts_test_result when the run was successful return; } public static function __post_test_run_process($obj = null) { // Passed is a copy of the pts_result_file_writer return; } public static function __post_run_process($obj = null) { // Passed is the current pts_test_run_manager, where accessible is an array of pts_test_result objects for all tests scheduled to run return; } // // Event-driven Functions // public static function __event_openbenchmarking_upload($obj = null) { // Passed is the decoded JSON response from OpenBenchmarking.org return; } public static function __event_results_process($obj = null) { // Passed is the pts_test_run_manager return; } public static function __event_results_saved($obj = null) { // Passed is a copy of the pts_test_run_manager return; } public static function __event_user_error($obj = null) { // TODO use __event_user_error return; } */ } ?> phoronix-test-suite/pts-core/objects/client/pts_external_dependencies.php0000644000175000017500000003615212222311407027211 0ustar michaelmichael. */ class pts_external_dependencies { public static function install_dependencies(&$test_profiles) { // PTS External Dependencies install on distribution if(phodevi::is_windows() || phodevi::is_macosx() || pts_flags::no_external_dependencies()) { // Windows doesn't use any external dependencies return true; } // Find all the tests that need to be checked $tests_to_check = array(); foreach($test_profiles as $test_profile) { if(!in_array($test_profile, $tests_to_check) && $test_profile->is_supported()) { array_push($tests_to_check, $test_profile); } } // Find all of the POSSIBLE test dependencies $required_test_dependencies = array(); foreach($tests_to_check as &$test_profile) { foreach($test_profile->get_dependencies() as $test_dependency) { if(empty($test_dependency)) { continue; } if(isset($required_test_dependencies[$test_dependency]) == false) { $required_test_dependencies[$test_dependency] = array(); } array_push($required_test_dependencies[$test_dependency], $test_profile); } } if(!empty($required_test_dependencies)) { // The 'common-dependencies' package is any general non-explicitly-required but nice-to-have packages like mesa-utils for providing glxinfo about the system // So if we're going to be installing external dependencies anyways, might as well try to see the common-dependencies are satisfied $required_test_dependencies['common-dependencies'] = array(); } // Does the user wish to skip any particular dependencies? if(pts_client::read_env('SKIP_EXTERNAL_DEPENDENCIES')) { $dependencies_to_skip = explode(',', pts_client::read_env('SKIP_EXTERNAL_DEPENDENCIES')); foreach($dependencies_to_skip as $dependency_name) { if(isset($required_test_dependencies[$dependency_name])) { unset($required_test_dependencies[$dependency_name]); } } } // Make a copy for use to check at end of process to see if all dependencies were actually found $required_test_dependencies_copy = $required_test_dependencies; // Find the dependencies that are actually missing from the system $dependencies_to_install = self::check_dependencies_missing_from_system($required_test_dependencies); // If it's automated and can't install without root, return true if there are no dependencies to do otherwise false if((pts_c::$test_flags & pts_c::auto_mode) && phodevi::is_root() == false) { return count($dependencies_to_install) == 0; } // Do the actual dependency install process if(count($dependencies_to_install) > 0) { self::install_packages_on_system($dependencies_to_install); } // There were some dependencies not supported on this OS or are missing from the distro's XML file if(count($required_test_dependencies) > 0 && count($dependencies_to_install) == 0) { $exdep_generic_parser = new pts_exdep_generic_parser(); $to_report = array(); foreach(array_keys($required_test_dependencies) as $dependency) { $dependency_data = $exdep_generic_parser->get_package_data($dependency); if($dependency_data['possible_packages'] != null) { array_push($to_report, $dependency_data['title'] . PHP_EOL . 'Possible Package Names: ' . $dependency_data['possible_packages']); } } if(count($to_report) > 0) { echo PHP_EOL . 'Some additional dependencies are required, but they could not be installed automatically for your operating system.' . PHP_EOL . 'Below are the software packages that must be installed.' . PHP_EOL . PHP_EOL; foreach($to_report as $report) { pts_client::$display->generic_heading($report); } if((pts_c::$test_flags ^ pts_c::batch_mode) && (pts_c::$test_flags ^ pts_c::auto_mode)) { echo 'The above dependencies should be installed before proceeding. Press any key when you\'re ready to continue.'; pts_user_io::read_user_input(); echo PHP_EOL; } } } // Find the dependencies that are still missing from the system if((pts_c::$test_flags ^ pts_c::batch_mode) && (pts_c::$test_flags ^ pts_c::auto_mode)) { $generic_packages_needed = array(); $required_test_dependencies = $required_test_dependencies_copy; $dependencies_to_install = self::check_dependencies_missing_from_system($required_test_dependencies_copy, $generic_packages_needed); if(count($generic_packages_needed) > 0) { echo PHP_EOL . 'There are dependencies still missing from the system:' . PHP_EOL; echo pts_user_io::display_text_list(self::generic_names_to_titles($generic_packages_needed)); $actions = array( 'IGNORE' => 'Ignore missing dependencies and proceed with installation.', 'SKIP_TESTS_WITH_MISSING_DEPS' => 'Skip installing the tests with missing dependencies.', 'REATTEMPT_DEP_INSTALL' => 'Re-attempt to install the missing dependencies.', 'QUIT' => 'Quit the current Phoronix Test Suite process.' ); $selected_action = pts_user_io::prompt_text_menu('Missing dependencies action', $actions, false, true); switch($selected_action) { case 'IGNORE': break; case 'SKIP_TESTS_WITH_MISSING_DEPS': // Unset the tests that have dependencies still missing foreach($generic_packages_needed as $pkg) { if(isset($required_test_dependencies[$pkg])) { foreach($required_test_dependencies[$pkg] as $test_with_this_dependency) { if(($index = array_search($test_with_this_dependency, $test_profiles)) !== false) { unset($test_profiles[$index]); } } } } break; case 'REATTEMPT_DEP_INSTALL': self::install_packages_on_system($dependencies_to_install); break; case 'QUIT': exit(0); } } } return true; } public static function all_dependency_names() { $exdep_generic_parser = new pts_exdep_generic_parser(); return $exdep_generic_parser->get_available_packages(); } public static function all_dependency_titles() { $dependency_names = self::all_dependency_names(); return self::generic_names_to_titles($dependency_names); } public static function missing_dependency_names() { $all_test_dependencies = array(); $all_missing_dependencies = array(); foreach(self::all_dependency_names() as $name) { $all_test_dependencies[$name] = array(); } self::check_dependencies_missing_from_system($all_test_dependencies, $all_missing_dependencies); sort($all_missing_dependencies); return $all_missing_dependencies; } public static function missing_dependency_titles() { $dependency_names = self::missing_dependency_names(); return self::generic_names_to_titles($dependency_names); } public static function installed_dependency_names() { $installed_test_dependencies = array_diff(self::all_dependency_names(), self::missing_dependency_names()); sort($installed_test_dependencies); return $installed_test_dependencies; } public static function installed_dependency_titles() { $dependency_names = self::installed_dependency_names(); return self::generic_names_to_titles($dependency_names); } private static function check_dependencies_missing_from_system(&$required_test_dependencies, &$generic_names_of_packages_needed = false) { $generic_dependencies_parser = new pts_exdep_generic_parser(); $vendor_dependencies_parser = new pts_exdep_platform_parser(self::vendor_identifier('package-list')); $kernel_architecture = phodevi::read_property('system', 'kernel-architecture'); $needed_os_packages = array(); foreach($required_test_dependencies as $package => $dependents) { if($vendor_dependencies_parser->is_package($package)) { $package_data = $vendor_dependencies_parser->get_package_data($package); $arch_compliant = empty($package_data['arch_specific']) || in_array($kernel_architecture, $package_data['arch_specific']); if(!empty($package_data['file_check'])) { $add_dependency = self::file_missing_check($package_data['file_check']); } else if($generic_dependencies_parser->is_package($package)) { // If the OS/platform-specific package didn't supply a file check list, obtain it from the generic listing $generic_package_data = $generic_dependencies_parser->get_package_data($package); $add_dependency = empty($generic_package_data['file_check']) || self::file_missing_check($generic_package_data['file_check']); } if($add_dependency && $arch_compliant && $package_data['os_package'] != null) { if(!in_array($package_data['os_package'], $needed_os_packages)) { array_push($needed_os_packages, $package_data['os_package']); } if($generic_names_of_packages_needed !== false && !in_array($package, $generic_names_of_packages_needed)) { array_push($generic_names_of_packages_needed, $package); } } else { unset($required_test_dependencies[$package]); } } } if(count($required_test_dependencies) > 0) { foreach($required_test_dependencies as $i => $dependency) { $package_data = $generic_dependencies_parser->get_package_data($i); $file_present = !empty($package_data['file_check']) && !self::file_missing_check($package_data['file_check']); if($file_present) { unset($required_test_dependencies[$i]); } } } return $needed_os_packages; } private static function file_missing_check($file_arr) { // Checks if file is missing $file_missing = false; if(!is_array($file_arr)) { $file_arr = pts_strings::comma_explode($file_arr); } foreach($file_arr as $file) { $file_is_there = false; $file = explode('OR', $file); for($i = 0; $i < count($file) && $file_is_there == false; $i++) { $file[$i] = trim($file[$i]); if(is_file($file[$i]) || is_dir($file[$i]) || is_link($file[$i])) { $file_is_there = true; } else if(isset($file[$i][2]) && $file[$i][0] != '/') { // See if it's some relative command/path if(substr($file[$i], -2) == '.h' || substr($file[$i], -4) == '.hpp') { // May just be a relative header file to look for... $possible_paths = array('/usr/local/include', '/usr/target/include/', '/usr/include/'); foreach($possible_paths as $path) { if(is_file($path . $file[$i]) || is_link($path . $file[$i])) { $file_is_there = true; } } } else if(strpos($file[$i], '.so') !== false || substr($file[$i], -2) == '.a') { // May just be a relative shared library to look for... $possible_paths = array('/usr/local/lib/', '/usr/lib/', '/usr/lib64/', '/usr/lib/x86_64-linux-gnu/', '/usr/lib/i386-linux-gnu/', '/usr/lib/arm-linux-gnueabihf/'); if(getenv('LD_LIBRARY_PATH')) { foreach(explode(':', getenv('LD_LIBRARY_PATH')) as $path) { array_push($possible_paths, $path . '/'); } } foreach($possible_paths as $path) { if(is_file($path . $file[$i]) || is_link($path . $file[$i])) { $file_is_there = true; } } } else if(strpos($file[$i], '/') === false) { // May just be a command to look for... $possible_paths = array('/usr/local/bin/', '/usr/bin/'); if(getenv('PATH')) { foreach(explode(':', getenv('PATH')) as $path) { array_push($possible_paths, $path . '/'); } } foreach($possible_paths as $path) { if(is_file($path . $file[$i]) || is_link($path . $file[$i])) { $file_is_there = true; } } } } } $file_missing = $file_missing || !$file_is_there; } return $file_missing; } private static function install_packages_on_system($os_packages_to_install) { // Do the actual installing process of packages using the distribution's package management system $vendor_install_file = PTS_EXDEP_PATH . 'scripts/install-' . self::vendor_identifier('installer') . '-packages.sh'; // Rebuild the array index since some OS package XML tags provide multiple package names in a single string $os_packages_to_install = explode(' ', implode(' ', $os_packages_to_install)); if(is_file($vendor_install_file)) { // hook into pts_client::$display here if it's desired echo PHP_EOL . 'The following dependencies are needed and will be installed: ' . PHP_EOL . PHP_EOL; echo pts_user_io::display_text_list($os_packages_to_install); echo PHP_EOL . 'This process may take several minutes.' . PHP_EOL; echo shell_exec('sh ' . $vendor_install_file . ' ' . implode(' ', $os_packages_to_install)); } else { if(phodevi::is_macosx() == false) { echo 'Distribution install script not found!'; } } } private static function vendor_identifier($type) { $os_vendor = phodevi::read_property('system', 'vendor-identifier'); switch($type) { case 'package-list': $file_check_success = is_file(PTS_EXDEP_PATH . 'xml/' . $os_vendor . '-packages.xml'); break; case 'installer': $file_check_success = is_file(PTS_EXDEP_PATH . 'scripts/install-' . $os_vendor . '-packages.sh'); break; } if($file_check_success == false) { // Check the aliases to figure out the upstream distribution $os_vendor = false; $exdep_generic_parser = new pts_exdep_generic_parser(); foreach($exdep_generic_parser->get_vendors_list() as $this_vendor) { $exdep_platform_parser = new pts_exdep_platform_parser($this_vendor); $aliases = $exdep_platform_parser->get_aliases(); if(in_array($os_vendor, $aliases)) { $os_vendor = $this_vendor; break; } } if($os_vendor == false) { // Attempt to match the current operating system by seeing what package manager matches foreach($exdep_generic_parser->get_vendors_list() as $this_vendor) { $exdep_platform_parser = new pts_exdep_platform_parser($this_vendor); $package_manager = $exdep_platform_parser->get_package_manager(); if($package_manager != null && pts_client::executable_in_path($package_manager)) { $os_vendor = $this_vendor; break; } } } } return $os_vendor; } private static function generic_names_to_titles($names) { $titles = array(); $generic_dependencies_parser = new pts_exdep_generic_parser(); foreach($generic_dependencies_parser->get_available_packages() as $package) { if(in_array($package, $names)) { $package_data = $generic_dependencies_parser->get_package_data($package); array_push($titles, $package_data['title']); } } sort($titles); return $titles; } } ?> phoronix-test-suite/pts-core/objects/client/pts_test_install_manager.php0000644000175000017500000001551312172337602027067 0ustar michaelmichael. */ class pts_test_install_manager { private $tests_to_install; private static $extra_caches = array(); public function __construct() { $this->tests_to_install = array(); } public static function add_external_download_cache($cache) { return !in_array($cache, self::$extra_caches) ? array_push(self::$extra_caches, $cache) : false; } public function add_test_profile($test_profile) { $added = false; if(($e = pts_client::read_env('SKIP_TESTS')) != false && (in_array($test_profile->get_identifier(false), pts_strings::comma_explode($e)) || in_array($test_profile->get_identifier(true), pts_strings::comma_explode($e)))) { //pts_client::$display->test_install_error($test_profile->get_identifier() . ' is being skipped from installation.'); } else { $added = pts_arrays::unique_push($this->tests_to_install, new pts_test_install_request($test_profile)); } return $added; } public function generate_download_file_lists() { pts_client::$display->test_install_progress_start('Determining File Requirements'); $test_count = count($this->tests_to_install); foreach($this->tests_to_install as $i => &$test_install_request) { $test_install_request->generate_download_object_list(); pts_client::$display->test_install_progress_update(($i / $test_count)); } pts_client::$display->test_install_progress_completed(); } public function check_download_caches_for_files() { pts_client::$display->test_install_progress_start('Searching Download Caches'); $test_count = count($this->tests_to_install); $remote_files = self::remote_files_available_in_download_caches(); $local_download_caches = self::local_download_caches(); $remote_download_caches = self::remote_download_caches(); foreach($this->tests_to_install as $i => &$test_install_request) { $test_install_request->scan_download_caches($local_download_caches, $remote_download_caches, $remote_files); pts_client::$display->test_install_progress_update(($i / $test_count)); } pts_client::$display->test_install_progress_completed(); } public function remote_files_available_in_download_caches() { $remote_download_files = array(); foreach(self::remote_download_caches() as $dc_directory) { if(($xml_dc_file = pts_network::http_get_contents($dc_directory . 'pts-download-cache.xml')) != false) { $xml_dc_parser = new nye_XmlReader($xml_dc_file); $dc_file = $xml_dc_parser->getXMLArrayValues('PhoronixTestSuite/DownloadCache/Package/FileName'); $dc_md5 = $xml_dc_parser->getXMLArrayValues('PhoronixTestSuite/DownloadCache/Package/MD5'); foreach(array_keys($dc_file) as $i) { if(!isset($remote_download_files[$dc_md5[$i]])) { $remote_download_files[$dc_md5[$i]] = array(); } array_push($remote_download_files[$dc_md5[$i]], $dc_directory . $dc_file[$i]); } } } return $remote_download_files; } public static function file_lookaside_test_installations($package_filename, $package_md5, $package_sha256) { // Check to see if the same package name with the same package check-sum is already present in another test installation $package_match = false; foreach(pts_file_io::glob(pts_client::test_install_root_path() . '*/*/' . $package_filename) as $possible_package_match) { // Check to see if the same package name with the same package check-sum is already present in another test installation if(pts_test_installer::validate_sha256_download_file($possible_package_match, $package_sha256) || pts_test_installer::validate_md5_download_file($possible_package_match, $package_md5)) { $package_match = $possible_package_match; break; } } return $package_match; } public static function remote_download_caches() { $cache_directories = array(); foreach(self::download_cache_locations() as $dc_directory) { if(pts_strings::is_url($dc_directory)) { array_push($cache_directories, $dc_directory); } } return $cache_directories; } public static function local_download_caches() { $local_cache_directories = array(); foreach(self::download_cache_locations() as $dc_directory) { if(!pts_strings::is_url($dc_directory) && is_dir($dc_directory)) { array_push($local_cache_directories, $dc_directory); } } return $local_cache_directories; } public function get_test_run_requests() { return $this->tests_to_install; } public function tests_to_install_count() { return count($this->tests_to_install); } public function next_in_install_queue() { return count($this->tests_to_install) > 0 ? array_shift($this->tests_to_install) : false; } public static function download_cache_locations() { static $cache_directories = null; if($cache_directories == null) { $cache_directories = array(); // Phoronix Test Suite System Cache Directories $additional_dir_checks = array('/var/cache/phoronix-test-suite/download-cache/', '/var/cache/phoronix-test-suite/'); foreach($additional_dir_checks as $dir_check) { if(is_dir($dir_check)) { array_push($cache_directories, $dir_check); break; } } // User Defined Directory Checking $dir_string = ($dir = pts_client::read_env('PTS_DOWNLOAD_CACHE')) != false ? $dir : null; foreach(array_merge(self::$extra_caches, pts_strings::colon_explode($dir_string)) as $dir_check) { if($dir_check == null) { continue; } $dir_check = pts_client::parse_home_directory($dir_check); if(pts_strings::is_url($dir_check) == false && !is_dir($dir_check)) { continue; } array_push($cache_directories, pts_strings::add_trailing_slash($dir_check)); } if(pts_config::read_bool_config('PhoronixTestSuite/Options/Installation/SearchMediaForCache', 'TRUE')) { $download_cache_dirs = array_merge( pts_file_io::glob('/media/*/download-cache/'), pts_file_io::glob('/media/*/*/download-cache/'), pts_file_io::glob('/run/media/*/*/download-cache/'), pts_file_io::glob('/Volumes/*/download-cache/') ); foreach($download_cache_dirs as $dir) { array_push($cache_directories, $dir); } } } return $cache_directories; } } ?> phoronix-test-suite/pts-core/objects/client/pts_test_run_manager.php0000644000175000017500000015561712202327536026236 0ustar michaelmichael. */ class pts_test_run_manager { public $result_file_writer = null; private $tests_to_run = array(); private $failed_tests_to_run = array(); private $last_test_run_index = 0; private $test_run_pos = 0; private $test_run_count = 0; private $file_name = null; private $file_name_title = null; private $results_identifier = null; private $run_description = null; private $force_save_results = false; private $prompt_save_results = true; private $post_run_message = null; private $pre_run_message = null; private $allow_sharing_of_results = true; private $auto_upload_to_openbenchmarking = false; private $is_pcqs = false; private $do_dynamic_run_count = false; private $dynamic_run_count_on_length_or_less; private $dynamic_run_count_std_deviation_threshold; private $dynamic_run_count_export_script; private static $test_run_process_active = false; private static $batch_mode_options = false; public function __construct($test_flags = 0) { pts_client::set_test_flags($test_flags); $this->do_dynamic_run_count = pts_config::read_bool_config('PhoronixTestSuite/Options/TestResultValidation/DynamicRunCount', 'TRUE'); $this->dynamic_run_count_on_length_or_less = pts_config::read_user_config('PhoronixTestSuite/Options/TestResultValidation/LimitDynamicToTestLength', 20); $this->dynamic_run_count_std_deviation_threshold = pts_config::read_user_config('PhoronixTestSuite/Options/TestResultValidation/StandardDeviationThreshold', 3.50); $this->dynamic_run_count_export_script = pts_config::read_user_config('PhoronixTestSuite/Options/TestResultValidation/ExportResultsTo', null); pts_module_manager::module_process('__run_manager_setup', $this); } public function is_pcqs() { return $this->is_pcqs; } public function do_dynamic_run_count() { return $this->do_dynamic_run_count; } public function auto_upload_to_openbenchmarking($do = true) { $this->auto_upload_to_openbenchmarking = ($do == true); } 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; } protected function add_test_result_object(&$test_result) { if($this->validate_test_to_run($test_result->test_profile)) { pts_arrays::unique_push($this->tests_to_run, $test_result); } } public function get_tests_to_run() { return $this->tests_to_run; } public function get_tests_to_run_identifiers() { $identifiers = array(); foreach($this->tests_to_run as $test_run_request) { array_push($identifiers, $test_run_request->test_profile->get_identifier()); } array_unique($identifiers); return $identifiers; } public function get_estimated_run_time($index = -1) { if($index == -1) { $index = $this->last_test_run_index; } $estimated_time = 0; for($i = $index; $i < count($this->tests_to_run); $i++) { $estimated_time += $this->tests_to_run[$i]->test_profile->get_estimated_run_time(); } return $estimated_time; } public function get_test_to_run($index) { $this->last_test_run_index = $index; return isset($this->tests_to_run[$index]) ? $this->tests_to_run[$index] : false; } public function get_test_count() { return count($this->tests_to_run); } public function force_results_save() { $this->force_save_results = true; } protected function do_save_results() { return $this->file_name != null; } public function get_file_name() { return $this->file_name; } public function get_title() { return $this->file_name_title; } public function get_results_identifier() { return $this->results_identifier; } public function get_description() { return $this->run_description; } public function get_notes() { return null; // TODO: Not Yet Implemented } public function get_internal_tags() { return null; } public function get_reference_id() { return null; } public function get_preset_environment_variables() { return pts_module_manager::var_store_string(); } public function result_already_contains_identifier() { $result_file = new pts_result_file($this->file_name); return in_array($this->results_identifier, $result_file->get_system_identifiers()); } public function set_save_name($save_name, $is_new_save = true) { if(empty($save_name)) { $save_name = date('Y-m-d-Hi'); } $this->file_name = self::clean_save_name($save_name, $is_new_save); $this->file_name_title = $save_name; $this->force_save_results = true; } public function set_results_identifier($identifier) { $this->results_identifier = self::clean_results_identifier($identifier); } public static function recently_saved_test_results() { $recent_results = array(); foreach(pts_file_io::glob(PTS_SAVE_RESULTS_PATH . '*/composite.xml') as $composite) { $recent_results[filemtime($composite)] = basename(dirname($composite)); } if(count($recent_results) > 0) { krsort($recent_results); $recent_results = array_slice($recent_results, 0, 4, true); $res_length = strlen(pts_strings::find_longest_string($recent_results)) + 2; $current_time = time(); foreach($recent_results as $m_time => &$recent_result) { $days = floor(($current_time - $m_time) / 86400); $recent_result = sprintf('%-' . $res_length . 'ls [%-ls]', $recent_result, ($days == 0 ? 'Today' : pts_strings::days_ago_format_string($days) . ' old')); } echo PHP_EOL . 'Recently Saved Test Results:' . PHP_EOL; echo pts_user_io::display_text_list($recent_results) . PHP_EOL; return true; } return false; } public function prompt_save_name() { if($this->file_name != null) { return; } // Prompt to save a file when running a test $save_name = null; if(($env = pts_client::read_env('TEST_RESULTS_NAME'))) { $save_name = $env; //echo 'Saving Results To: ' . $proposed_name . PHP_EOL; } if((pts_c::$test_flags ^ pts_c::batch_mode) || self::$batch_mode_options['PromptSaveName']) { $is_reserved_word = false; // Be of help to the user by showing recently saved test results if($save_name == null) { self::recently_saved_test_results(); } while(empty($save_name) || ($is_reserved_word = pts_types::is_test_or_suite($save_name))) { if($is_reserved_word) { echo PHP_EOL . 'The name of the saved file cannot be the same as a test/suite: ' . $save_name . PHP_EOL; $is_reserved_word = false; } pts_client::$display->generic_prompt('Enter a name to save these results under: '); $save_name = pts_user_io::read_user_input(); } } $this->set_save_name($save_name); } public function prompt_results_identifier() { // Prompt for a results identifier $results_identifier = null; $show_identifiers = array(); $no_repeated_tests = true; if(pts_result_file::is_test_result_file($this->file_name)) { $result_file = new pts_result_file($this->file_name); $current_identifiers = $result_file->get_system_identifiers(); $current_hardware = $result_file->get_system_hardware(); $current_software = $result_file->get_system_software(); $result_objects = $result_file->get_result_objects(); foreach(array_keys($result_objects) as $result_key) { $result_objects[$result_key] = $result_objects[$result_key]->get_comparison_hash(false); } foreach($this->tests_to_run as &$run_request) { if($run_request instanceof pts_test_result && in_array($run_request->get_comparison_hash(), $result_objects)) { $no_repeated_tests = false; break; } } } else { $current_identifiers = array(); $current_hardware = array(); $current_software = array(); } if((pts_c::$test_flags ^ pts_c::batch_mode) || self::$batch_mode_options['PromptForTestIdentifier'] && (pts_c::$test_flags ^ pts_c::auto_mode) && (pts_c::$test_flags ^ pts_c::is_recovering)) { if(count($current_identifiers) > 0) { echo PHP_EOL . 'Current Test Identifiers:' . PHP_EOL; echo pts_user_io::display_text_list($current_identifiers); echo PHP_EOL; } $times_tried = 0; do { if($times_tried == 0 && ($env_identifier = pts_client::read_env('TEST_RESULTS_IDENTIFIER'))) { $results_identifier = isset($env_identifier) ? $env_identifier : null; echo 'Test Identifier: ' . self::clean_results_identifier($results_identifier) . PHP_EOL; } else if((pts_c::$test_flags ^ pts_c::auto_mode)) { pts_client::$display->generic_prompt('Enter a unique name to describe this test run / configuration: '); $results_identifier = self::clean_results_identifier(pts_user_io::read_user_input()); } $times_tried++; $identifier_pos = (($p = array_search($results_identifier, $current_identifiers)) !== false ? $p : -1); if((pts_c::$test_flags & pts_c::auto_mode)) { // Make sure if in auto-mode we don't get stuck in a loop break; } } while((!$no_repeated_tests && $identifier_pos != -1) || (isset($current_hardware[$identifier_pos]) && $current_hardware[$identifier_pos] != phodevi::system_hardware(true)) || (isset($current_software[$identifier_pos]) && $current_software[$identifier_pos] != phodevi::system_software(true))); } if(empty($results_identifier)) { // If the save result identifier is empty, try to come up with something based upon the tests being run. $subsystem_r = array(); $subsystems_to_test = $this->subsystems_under_test(); if(pts_result_file::is_test_result_file($this->file_name)) { $result_file = new pts_result_file($this->file_name); $result_file_intent = pts_result_file_analyzer::analyze_result_file_intent($result_file); if(is_array($result_file_intent) && $result_file_intent[0] != 'Unknown') { array_unshift($subsystems_to_test, $result_file_intent[0]); } } foreach($subsystems_to_test as $subsystem) { $components = pts_result_file_analyzer::system_component_string_to_array(phodevi::system_hardware(true) . ', ' . phodevi::system_software(true)); if(isset($components[$subsystem])) { $subsystem_name = pts_strings::trim_search_query($components[$subsystem]); if(phodevi::is_vendor_string($subsystem_name) && !in_array($subsystem_name, $subsystem_r)) { array_push($subsystem_r, $subsystem_name); } if(isset($subsystem_r[2]) || isset($subsystem_name[19])) { break; } } } if(isset($subsystem_r[0])) { $results_identifier = implode(' - ', $subsystem_r); } if(empty($results_identifier)) { $results_identifier = date('Y-m-d H:i'); } } $this->results_identifier = $results_identifier; } public static function clean_results_identifier($results_identifier) { $results_identifier = trim(pts_client::swap_variables($results_identifier, array('pts_client', 'user_run_save_variables'))); $results_identifier = pts_strings::remove_redundant(pts_strings::keep_in_string($results_identifier, pts_strings::CHAR_LETTER | pts_strings::CHAR_NUMERIC | pts_strings::CHAR_DASH | pts_strings::CHAR_UNDERSCORE | pts_strings::CHAR_COLON | pts_strings::CHAR_COMMA | pts_strings::CHAR_SLASH | pts_strings::CHAR_SPACE | pts_strings::CHAR_DECIMAL | pts_strings::CHAR_AT | pts_strings::CHAR_PLUS | pts_strings::CHAR_SEMICOLON | pts_strings::CHAR_EQUAL), ' '); return $results_identifier; } public function get_test_run_position() { return $this->test_run_pos + 1; } public function get_test_run_count_reported() { return $this->test_run_count; } public function call_test_runs() { // Create a lock $lock_path = pts_client::temporary_directory() . '/phoronix-test-suite.active'; pts_client::create_lock($lock_path); if($this->pre_run_message != null) { pts_user_io::display_interrupt_message($this->pre_run_message); } // Hook into the module framework self::$test_run_process_active = true; pts_module_manager::module_process('__pre_run_process', $this); pts_file_io::unlink(PTS_USER_PATH . 'halt-testing'); pts_file_io::unlink(PTS_USER_PATH . 'skip-test'); $continue_test_flag = true; $tests_to_run_count = $this->get_test_count(); pts_client::$display->test_run_process_start($this); $total_loop_count = (($t = pts_client::read_env('TOTAL_LOOP_COUNT')) && is_numeric($t) && $t > 0) ? $t : 1; $total_loop_time = (($t = pts_client::read_env('TOTAL_LOOP_TIME')) && is_numeric($t) && $t > 60) ? ($t * 60) : -1; $loop_end_time = $total_loop_time != -1 ? (time() + $total_loop_time) : false; $this->test_run_count = ($tests_to_run_count * $total_loop_count); for($loop = 1; $loop <= $total_loop_count && $continue_test_flag; $loop++) { for($i = 0; $i < $tests_to_run_count && $continue_test_flag; $i++) { $this->test_run_pos = $i; $continue_test_flag = $this->process_test_run_request($i); if(pts_flags::remove_test_on_completion()) { // Remove the installed test if it's no longer needed in this run queue $this_test_profile_identifier = $this->get_test_to_run($this->test_run_pos)->test_profile->get_identifier(); $still_in_queue = false; for($j = ($this->test_run_pos + 1); $j < $tests_to_run_count && $still_in_queue == false; $j++) { if($this->get_test_to_run($j)->test_profile->get_identifier() == $this_test_profile_identifier) { $still_in_queue = true; } } if($still_in_queue == false) { pts_client::remove_installed_test($this->get_test_to_run($this->test_run_pos)->test_profile); } } if($loop_end_time) { if(time() > $loop_end_time) { $continue_test_flag = false; } else if($this->test_run_count == ($i + 1)) { // There's still time remaining so increase the run count.... $this->test_run_count += $tests_to_run_count; } } } } pts_file_io::unlink(PTS_SAVE_RESULTS_PATH . $this->get_file_name() . '/active.xml'); foreach($this->tests_to_run as &$run_request) { // Remove cache shares foreach(pts_file_io::glob($run_request->test_profile->get_install_dir() . 'cache-share-*.pt2so') as $cache_share_file) { unlink($cache_share_file); } } if($this->post_run_message != null) { pts_user_io::display_interrupt_message($this->post_run_message); } self::$test_run_process_active = -1; pts_module_manager::module_process('__post_run_process', $this); pts_client::release_lock($lock_path); // Report any tests that failed to properly run if((pts_c::$test_flags ^ pts_c::batch_mode) || (pts_c::$test_flags & pts_c::debug_mode) || $this->get_test_count() > 3) { if(count($this->failed_tests_to_run) > 0) { echo PHP_EOL . PHP_EOL . 'The following tests failed to properly run:' . PHP_EOL . PHP_EOL; foreach($this->failed_tests_to_run as &$run_request) { echo "\t- " . $run_request->test_profile->get_identifier() . ($run_request->get_arguments_description() != null ? ': ' . $run_request->get_arguments_description() : null) . PHP_EOL; } echo PHP_EOL; } } } public static function test_run_process_active() { return self::$test_run_process_active = true; } private function process_test_run_request($run_index) { $result = false; if($this->get_file_name() != null) { $this->result_file_writer->save_xml(PTS_SAVE_RESULTS_PATH . $this->get_file_name() . '/active.xml'); } $test_run_request = $this->get_test_to_run($run_index); if(($run_index != 0 && count(pts_file_io::glob($test_run_request->test_profile->get_install_dir() . 'cache-share-*.pt2so')) == 0)) { // Sleep for six seconds between tests by default sleep(6); } pts_test_execution::run_test($this, $test_run_request); if(pts_file_io::unlink(PTS_USER_PATH . 'halt-testing')) { // Stop the testing process entirely return false; } else if(pts_file_io::unlink(PTS_USER_PATH . 'skip-test')) { // Just skip the current test and do not save the results, but continue testing continue; } $test_successful = false; if($test_run_request->test_profile->get_display_format() == 'NO_RESULT') { $test_successful = true; } else if($test_run_request instanceof pts_test_result) { $end_result = $test_run_request->get_result(); // removed count($result) > 0 in the move to pts_test_result if(count($test_run_request) > 0 && ((is_numeric($end_result) && $end_result > 0) || (!is_numeric($end_result) && isset($end_result[3])))) { pts_module_manager::module_process('__post_test_run_success', $test_run_request); $test_identifier = $this->get_results_identifier(); $test_successful = true; if(!empty($test_identifier)) { $this->result_file_writer->add_result_from_result_object_with_value_string($test_run_request, $test_run_request->get_result(), $test_run_request->test_result_buffer->get_values_as_string(), self::process_json_report_attributes($test_run_request)); if($test_run_request->secondary_linked_results != null && is_array($test_run_request->secondary_linked_results)) { foreach($test_run_request->secondary_linked_results as &$run_request_minor) { if(strpos($run_request_minor->get_arguments_description(), $test_run_request->get_arguments_description()) === false) { $run_request_minor->set_used_arguments_description($test_run_request->get_arguments_description() . ' - ' . $run_request_minor->get_arguments_description()); } $this->result_file_writer->add_result_from_result_object_with_value_string($run_request_minor, $run_request_minor->get_result(), null, self::process_json_report_attributes($run_request_minor)); } } if($this->get_results_identifier() != null && $this->get_file_name() != null && pts_config::read_bool_config('PhoronixTestSuite/Options/Testing/SaveTestLogs', 'FALSE')) { static $xml_write_pos = 1; pts_file_io::mkdir(PTS_SAVE_RESULTS_PATH . $this->get_file_name() . '/test-logs/' . $xml_write_pos . '/'); if(is_dir(PTS_SAVE_RESULTS_PATH . $this->get_file_name() . '/test-logs/active/' . $this->get_results_identifier())) { $test_log_write_dir = PTS_SAVE_RESULTS_PATH . $this->get_file_name() . '/test-logs/' . $xml_write_pos . '/' . $this->get_results_identifier() . '/'; if(is_dir($test_log_write_dir)) { pts_file_io::delete($test_log_write_dir, null, true); } rename(PTS_SAVE_RESULTS_PATH . $this->get_file_name() . '/test-logs/active/' . $this->get_results_identifier() . '/', $test_log_write_dir); } $xml_write_pos++; } } } pts_file_io::unlink(PTS_SAVE_RESULTS_PATH . $this->get_file_name() . '/test-logs/active/'); } if($test_successful == false && $test_run_request->test_profile->get_identifier() != null) { array_push($this->failed_tests_to_run, $test_run_request); // For now delete the failed test log files, but it may be a good idea to keep them pts_file_io::delete(PTS_SAVE_RESULTS_PATH . $this->get_file_name() . '/test-logs/active/' . $this->get_results_identifier() . '/', null, true); } pts_module_manager::module_process('__post_test_run_process', $this->result_file_writer); return true; } protected static function process_json_report_attributes(&$test_run_request) { // XXX : add to attributes JSON here $json_report_attributes = null; if(($t = $test_run_request->test_profile->test_installation->get_compiler_data())) { $json_report_attributes['compiler-options'] = $t; } if(($t = $test_run_request->get_min_result()) != 0) { $json_report_attributes['min-result'] = $t; } if(($t = $test_run_request->get_max_result()) != 0) { $json_report_attributes['max-result'] = $t; } return $json_report_attributes; } public static function clean_save_name($input, $is_new_save = true) { $input = pts_client::swap_variables($input, array('pts_client', 'user_run_save_variables')); $input = pts_strings::remove_redundant(pts_strings::keep_in_string(str_replace(' ', '-', trim($input)), pts_strings::CHAR_LETTER | pts_strings::CHAR_NUMERIC | pts_strings::CHAR_DASH), '-'); if($is_new_save) { $input = strtolower($input); } return $input; } public static function initial_checks(&$to_run, $test_flags = 0) { // Refresh the pts_client::$display in case we need to run in debug mode $test_flags |= pts_c::is_run_process; pts_client::init_display_mode($test_flags); pts_client::set_test_flags($test_flags); $to_run = pts_types::identifiers_to_objects($to_run); if((pts_c::$test_flags & pts_c::batch_mode)) { if(self::$batch_mode_options === false) { self::set_batch_mode(); } if(self::$batch_mode_options['Configured'] == false && (pts_c::$test_flags ^ pts_c::auto_mode)) { pts_client::$display->generic_error('The batch mode must first be configured.' . PHP_EOL . 'To configure, run phoronix-test-suite batch-setup'); return false; } } if(!is_writable(pts_client::test_install_root_path())) { pts_client::$display->generic_error('The test installation directory is not writable.' . PHP_EOL . 'Location: ' . pts_client::test_install_root_path()); return false; } // Cleanup tests to run if(pts_test_run_manager::cleanup_tests_to_run($to_run) == false) { return false; } else if(count($to_run) == 0) { pts_client::$display->generic_error('You must enter at least one test, suite, or result identifier to run.'); return false; } return true; } public function pre_execution_process() { if($this->do_save_results()) { $this->result_file_writer = new pts_result_file_writer($this->get_results_identifier()); if((pts_c::$test_flags ^ pts_c::is_recovering) && (!pts_result_file::is_test_result_file($this->get_file_name()) || $this->result_already_contains_identifier() == false)) { $this->result_file_writer->add_result_file_meta_data($this); $this->result_file_writer->add_current_system_information(); } pts_client::setup_test_result_directory($this->get_file_name()); } } protected function generate_json_system_attributes() { $test_external_dependencies = array(); $test_hardware_types = array(); $test_internal_tags = array(); foreach($this->tests_to_run as $test_to_run) { $test_external_dependencies = array_merge($test_external_dependencies, $test_to_run->test_profile->get_dependencies()); $test_internal_tags = array_merge($test_internal_tags, $test_to_run->test_profile->get_internal_tags()); pts_arrays::unique_push($test_hardware_types, $test_to_run->test_profile->get_test_hardware_type()); } return self::pull_test_notes(false, $test_external_dependencies, $test_internal_tags, $test_hardware_types); } public static function pull_test_notes($show_all = false, $test_external_dependencies = array(), $test_internal_tags = array(), $test_hardware_types = array()) { $notes = null; if($show_all || in_array('build-utilities', $test_external_dependencies)) { // So compiler tests were run.... $test = false; $compiler_mask_dir = pts_test_installer::create_compiler_mask($test); if($compiler_mask_dir && is_executable($compiler_mask_dir . 'cc')) { $compiler_configuration = phodevi_system::sw_compiler_build_configuration($compiler_mask_dir . 'cc'); pts_file_io::delete($compiler_mask_dir, null, true); if(!empty($compiler_configuration)) { $notes['compiler-configuration'] = $compiler_configuration; } } } if($show_all || in_array('OpenCL', $test_internal_tags)) { // So OpenCL tests were run.... $gpu_compute_cores = phodevi::read_property('gpu', 'compute-cores'); if($gpu_compute_cores > 0) { $notes['graphics-compute-cores'] = $gpu_compute_cores; } } if($show_all || in_array('Disk', $test_hardware_types)) { // A disk test was run so report some disk information... $disk_scheduler = phodevi::read_property('disk', 'scheduler'); if($disk_scheduler) { $notes['disk-scheduler'] = $disk_scheduler; } $mount_options = phodevi::read_property('disk', 'mount-options'); if(isset($mount_options['mount-options']) && $mount_options['mount-options'] != null) { $notes['disk-mount-options'] = $mount_options['mount-options']; } } if($show_all || in_array('Processor', $test_hardware_types) || in_array('System', $test_hardware_types)) { $scaling_governor = phodevi::read_property('cpu', 'scaling-governor'); if($scaling_governor) { $notes['cpu-scaling-governor'] = $scaling_governor; } } if($show_all || in_array('Graphics', $test_hardware_types)) { $accel_2d = phodevi::read_property('gpu', '2d-acceleration'); if($accel_2d) { $notes['graphics-2d-acceleration'] = $accel_2d; } $aa = phodevi::read_property('gpu', 'aa-level'); if($aa) { $notes['graphics-aa'] = $aa; } $af = phodevi::read_property('gpu', 'af-level'); if($af) { $notes['graphics-af'] = $af; } } if(phodevi::read_property('system', 'kernel-parameters')) { $notes['kernel-parameters'] = phodevi::read_property('system', 'kernel-parameters'); } if(phodevi::read_property('system', 'environment-variables')) { $notes['environment-variables'] = phodevi::read_property('system', 'environment-variables'); } return $notes; } public function post_execution_process() { if($this->do_save_results()) { if($this->result_file_writer->get_result_count() == 0 && !pts_result_file::is_test_result_file($this->get_file_name()) && (pts_c::$test_flags ^ pts_c::is_recovering) && (pts_c::$test_flags ^ pts_c::remote_mode)) { pts_file_io::delete(PTS_SAVE_RESULTS_PATH . $this->get_file_name()); return false; } pts_file_io::delete(PTS_SAVE_RESULTS_PATH . $this->get_file_name() . '/test-logs/active/', null, true); if((pts_c::$test_flags ^ pts_c::is_recovering) && (!pts_result_file::is_test_result_file($this->get_file_name()) || $this->result_already_contains_identifier() == false)) { $this->result_file_writer->add_test_notes(pts_test_notes_manager::generate_test_notes($this->tests_to_run), $this->generate_json_system_attributes()); } echo PHP_EOL; pts_module_manager::module_process('__event_results_process', $this); pts_client::save_result_file($this->result_file_writer, $this->get_file_name()); pts_module_manager::module_process('__event_results_saved', $this); //echo PHP_EOL . 'Results Saved To: ; . PTS_SAVE_RESULTS_PATH . $this->get_file_name() . ;/composite.xml' . PHP_EOL; $auto_open = (pts_c::$test_flags & pts_c::batch_mode) ? self::$batch_mode_options['OpenBrowser'] : false; pts_client::display_web_page(PTS_SAVE_RESULTS_PATH . $this->get_file_name() . '/index.html', null, true, $auto_open); if($this->allow_sharing_of_results && pts_network::network_support_available()) { if($this->auto_upload_to_openbenchmarking || pts_openbenchmarking_client::auto_upload_results() || pts_flags::upload_to_openbenchmarking()) { $upload_results = true; } else if((pts_c::$test_flags & pts_c::batch_mode)) { $upload_results = self::$batch_mode_options['UploadResults']; } else if((pts_c::$test_flags ^ pts_c::auto_mode)) { $upload_results = pts_user_io::prompt_bool_input('Would you like to upload the results to OpenBenchmarking.org', true); } else { $upload_results = false; } if($upload_results) { $upload_url = pts_openbenchmarking::upload_test_result($this); if(!empty($upload_url)) { if((pts_c::$test_flags ^ pts_c::auto_mode) && pts_openbenchmarking_client::auto_upload_results() == false) { pts_client::display_web_page($upload_url, 'Do you want to launch OpenBenchmarking.org', true); } } else { echo PHP_EOL . 'Results Failed To Upload.' . PHP_EOL; } } } } } public static function set_batch_mode($custom_preset = false) { self::$batch_mode_options = array( 'UploadResults' => pts_config::read_bool_config('PhoronixTestSuite/Options/BatchMode/UploadResults', 'TRUE'), 'SaveResults' => pts_config::read_user_config('PhoronixTestSuite/Options/BatchMode/SaveResults', 'TRUE'), 'PromptForTestDescription' => pts_config::read_bool_config('PhoronixTestSuite/Options/BatchMode/PromptForTestDescription', 'FALSE'), 'RunAllTestCombinations' => pts_config::read_bool_config('PhoronixTestSuite/Options/BatchMode/RunAllTestCombinations', 'TRUE'), 'PromptSaveName' => pts_config::read_bool_config('PhoronixTestSuite/Options/BatchMode/PromptSaveName', 'FALSE'), 'PromptForTestIdentifier' => pts_config::read_bool_config('PhoronixTestSuite/Options/BatchMode/PromptForTestIdentifier', 'TRUE'), 'Configured' => pts_config::read_bool_config('PhoronixTestSuite/Options/BatchMode/Configured', 'FALSE'), 'OpenBrowser' => pts_config::read_bool_config('PhoronixTestSuite/Options/BatchMode/OpenBrowser', 'FALSE'), ); if($custom_preset && is_array($custom_preset)) { foreach($custom_preset as $key => $value) { self::$batch_mode_options[$key] = $value; } self::$batch_mode_options['Configured'] = true; } } public static function cleanup_tests_to_run(&$to_run_objects) { $skip_tests = ($e = pts_client::read_env('SKIP_TESTS')) ? pts_strings::comma_explode($e) : false; $tests_verified = array(); $tests_missing = array(); foreach($to_run_objects as &$run_object) { if($skip_tests && (in_array($run_object->get_identifier(false), $skip_tests) || ($run_object instanceof pts_test_profile && in_array($run_object->get_identifier_base_name(), $skip_tests)))) { echo 'Skipping: ' . $run_object->get_identifier() . PHP_EOL; continue; } else if($run_object instanceof pts_test_profile) { if($run_object->get_title() == null) { echo 'Not A Test: ' . $run_object . PHP_EOL; continue; } else { if($run_object->is_supported(false) == false) { continue; } if($run_object->is_test_installed() == false) { // Check to see if older version of test is currently installed // TODO: show change-log between installed versions and upstream array_push($tests_missing, $run_object); continue; } } } else if($run_object instanceof pts_result_file) { $num_installed = 0; foreach($run_object->get_contained_test_profiles() as $test_profile) { if($test_profile == null || $test_profile->get_identifier() == null || $test_profile->is_supported(false) == false) { continue; } else if($test_profile->is_test_installed() == false) { array_push($tests_missing, $test_profile); } else { $num_installed++; } } if($num_installed == 0) { continue; } } else if($run_object instanceof pts_test_suite || $run_object instanceof pts_virtual_test_suite) { if($run_object->is_core_version_supported() == false) { echo $run_object->get_title() . ' is a suite not supported by this version of the Phoronix Test Suite.' . PHP_EOL; continue; } $num_installed = 0; foreach($run_object->get_contained_test_profiles() as $test_profile) { if($test_profile == null || $test_profile->get_identifier() == null || $test_profile->is_supported(false) == false) { continue; } if($test_profile->is_test_installed() == false) { array_push($tests_missing, $test_profile); } else { $num_installed++; } } if($num_installed == 0) { continue; } } else { echo 'Not Recognized: ' . $run_object . PHP_EOL; continue; } array_push($tests_verified, $run_object); } $to_run_objects = $tests_verified; if(count($tests_missing) > 0) { $tests_missing = array_unique($tests_missing); if(count($tests_missing) == 1) { pts_client::$display->generic_error($tests_missing[0] . ' is not installed.'); // PHP_EOL . 'To install, run: phoronix-test-suite install ' . $tests_missing[0] } else { $message = PHP_EOL . PHP_EOL . 'Multiple tests are not installed:' . PHP_EOL . PHP_EOL; $message .= pts_user_io::display_text_list($tests_missing); //$message .= PHP_EOL . 'To install, run: phoronix-test-suite install ' . implode(' ', $tests_missing) . PHP_EOL . PHP_EOL; echo $message; } if((pts_c::$test_flags & pts_c::auto_mode) == false && (pts_c::$test_flags & pts_c::batch_mode) == false && pts_flags::is_live_cd() == false && pts_client::current_command() != 'benchmark') { $stop_and_install = pts_user_io::prompt_bool_input('Would you like to stop and install these tests now', true); if($stop_and_install) { pts_test_installer::standard_install($tests_missing, pts_c::$test_flags); self::cleanup_tests_to_run($to_run_objects); } } } return true; } public function auto_save_results($save_name, $result_identifier, $description = null) { $this->set_save_name($save_name, false); $this->set_results_identifier($result_identifier); $this->set_description($description); } public function set_description($description) { $this->run_description = $description == null ? self::auto_generate_description() : $description; } public function subsystems_under_test() { $subsystems_to_test = array(); foreach($this->tests_to_run as $test_run_request) { pts_arrays::unique_push($subsystems_to_test, $test_run_request->test_profile->get_test_hardware_type()); } return $subsystems_to_test; } protected function auto_generate_description() { $hw_components = array(pts_result_file_analyzer::system_component_string_to_array(phodevi::system_hardware(true))); $sw_components = array(pts_result_file_analyzer::system_component_string_to_array(phodevi::system_software(true))); if(pts_result_file::is_test_result_file($this->file_name)) { $result_file = new pts_result_file($this->file_name); $existing_identifier_count = count($result_file->get_system_identifiers()); foreach($result_file->get_system_hardware() as $component_string) { array_push($hw_components, pts_result_file_analyzer::system_component_string_to_array($component_string)); } foreach($result_file->get_system_software() as $component_string) { array_push($sw_components, pts_result_file_analyzer::system_component_string_to_array($component_string)); } } else { $existing_identifier_count = 0; } $auto_description = 'Running ' . implode(', ', array_unique($this->get_tests_to_run_identifiers())); $subsystems_to_test = $this->subsystems_under_test(); // TODO: hook into $hw_components and $sw_components for leveraging existing result file data for comparisons already in existent // dropped: count($subsystems_to_test) == 1 && $ if($existing_identifier_count == 0) { switch($subsystems_to_test) { case 'Graphics': $auto_description = phodevi::read_property('gpu', 'model') . ' graphics testing with ' . phodevi::read_property('system', 'display-driver-string') . ' / ' . phodevi::read_property('system', 'opengl-driver'); break; case 'Disk': $auto_description = phodevi::read_name('disk') . ' testing on ' . phodevi::read_property('system', 'operating-system') . ' with a ' . phodevi::read_property('system', 'filesystem') . ' file-system'; break; case 'Memory': case 'Processor': $auto_description = phodevi::read_property('cpu', 'model') . ' testing with a ' . phodevi::read_name('motherboard') . ' on ' . phodevi::read_property('system', 'operating-system'); break; default: if(phodevi::read_property('system', 'system-layer')) { // Virtualization, Wine testing... $auto_description = phodevi::read_property('system', 'system-layer') . ' testing on ' . phodevi::read_property('system', 'operating-system'); } else if(phodevi::read_name('motherboard') != null && phodevi::read_property('gpu', 'model') != null) { // Standard description $auto_description = phodevi::read_property('cpu', 'model') . ' testing with a ' . phodevi::read_name('motherboard') . ' and ' . phodevi::read_property('gpu', 'model') . ' on ' . phodevi::read_property('system', 'operating-system'); } else { // A virtualized environment or a BSD or other OS where not all hardware info is available... $auto_description = phodevi::read_property('cpu', 'model') . ' testing on ' . phodevi::read_property('system', 'operating-system'); } break; } } else { if(pts_result_file::is_test_result_file($this->file_name)) { $result_file = new pts_result_file($this->file_name); $result_file_intent = pts_result_file_analyzer::analyze_result_file_intent($result_file); if(is_array($result_file_intent) && $result_file_intent[0] != 'Unknown') { $auto_description = 'A ' . $result_file_intent[0] . ' comparison'; } } } $auto_description .= ' via the Phoronix Test Suite.'; return $auto_description; } public function save_results_prompt() { if((pts_c::$test_flags ^ pts_c::auto_mode)) { pts_client::$display->generic_heading('System Information'); echo 'Hardware:' . PHP_EOL . phodevi::system_hardware(true) . PHP_EOL . PHP_EOL; echo 'Software:' . PHP_EOL . phodevi::system_software(true) . PHP_EOL . PHP_EOL; } if(($this->prompt_save_results || $this->force_save_results) && count($this->tests_to_run) > 0) // or check for DO_NOT_SAVE_RESULTS == false { if($this->force_save_results || pts_client::read_env('TEST_RESULTS_NAME')) { $save_results = true; } else if((pts_c::$test_flags & pts_c::batch_mode)) { $save_results = self::$batch_mode_options['SaveResults']; } else { $save_results = pts_user_io::prompt_bool_input('Would you like to save these test results', true); } if($save_results) { // Prompt Save File Name $this->prompt_save_name(); // Prompt Identifier $this->prompt_results_identifier(); if(!isset($this->run_description[16]) || strpos($this->run_description, 'via the Phoronix Test Suite') !== false) { // Write the auto-description if nothing is set or attempt to auto-detect if it was a previous auto-description saved $this->run_description = self::auto_generate_description(); } // Prompt Description if((pts_c::$test_flags ^ pts_c::batch_mode) || self::$batch_mode_options['PromptForTestDescription']) { if($this->run_description == null) { $this->run_description = 'N/A'; } if(pts_client::read_env('TEST_RESULTS_DESCRIPTION')) { if(strlen(pts_client::read_env('TEST_RESULTS_DESCRIPTION')) > 1) { $this->run_description = pts_client::read_env('TEST_RESULTS_DESCRIPTION'); echo 'Test Description: ' . $this->run_description . PHP_EOL; } } else if((pts_c::$test_flags ^ pts_c::auto_mode)) { pts_client::$display->generic_heading('If you wish, enter a new description below to better describe this result set / system configuration under test.' . PHP_EOL . 'Press ENTER to proceed without changes.'); echo 'Current Description: ' . $this->run_description . PHP_EOL . PHP_EOL . 'New Description: '; $new_test_description = pts_user_io::read_user_input(); if(!empty($new_test_description)) { $this->run_description = $new_test_description; } } } } } } public function load_tests_to_run(&$to_run_objects) { // Determine what to run $this->determine_tests_to_run($to_run_objects); // Is there something to run? return $this->get_test_count() > 0; } public function load_result_file_to_run($save_name, $result_identifier, &$result_file, $tests_to_complete = null) { // Determine what to run $this->auto_save_results($save_name, $result_identifier); $this->run_description = $result_file->get_description(); $result_objects = $result_file->get_result_objects(); // Unset result objects that shouldn't be run if(is_array($tests_to_complete)) { foreach(array_keys($result_objects) as $i) { if(!in_array($i, $tests_to_complete)) { unset($result_objects[$i]); } } } if(count($result_objects) == 0) { return false; } foreach($result_objects as &$result_object) { if($this->validate_test_to_run($result_object->test_profile)) { $test_result = new pts_test_result($result_object->test_profile); $test_result->set_used_arguments($result_object->get_arguments()); $test_result->set_used_arguments_description($result_object->get_arguments_description()); $this->add_test_result_object($test_result); } } // Is there something to run? return $this->get_test_count() > 0; } public function load_test_run_requests_to_run($save_name, $result_identifier, &$result_file, &$test_run_requests) { // Determine what to run $this->auto_save_results($save_name, $result_identifier); $this->run_description = $result_file->get_description(); if(count($test_run_requests) == 0) { return false; } foreach($test_run_requests as &$test_run_request) { if($this->validate_test_to_run($test_run_request->test_profile) == false) { continue; } if($test_run_request->test_profile->get_override_values() != null) { $test_run_request->test_profile->set_override_values($test_run_request->test_profile->get_override_values()); } $test_result = new pts_test_result($test_run_request->test_profile); $test_result->set_used_arguments($test_run_request->get_arguments()); $test_result->set_used_arguments_description($test_run_request->get_arguments_description()); $this->add_test_result_object($test_result); } // Is there something to run? return $this->get_test_count() > 0; } protected function test_prompts_to_result_objects(&$test_profile) { $result_objects = array(); if((pts_c::$test_flags & pts_c::batch_mode) && self::$batch_mode_options['RunAllTestCombinations']) { list($test_arguments, $test_arguments_description) = pts_test_run_options::batch_user_options($test_profile); } else if((pts_c::$test_flags & pts_c::defaults_mode)) { list($test_arguments, $test_arguments_description) = pts_test_run_options::default_user_options($test_profile); } else { list($test_arguments, $test_arguments_description) = pts_test_run_options::prompt_user_options($test_profile); } foreach(array_keys($test_arguments) as $i) { $test_result = new pts_test_result($test_profile); $test_result->set_used_arguments($test_arguments[$i]); $test_result->set_used_arguments_description($test_arguments_description[$i]); array_push($result_objects, $test_result); } return $result_objects; } public function determine_tests_to_run(&$to_run_objects) { $unique_test_count = count(array_unique($to_run_objects)); $run_contains_a_no_result_type = false; $request_results_save = false; foreach($to_run_objects as &$run_object) { // TODO: determine whether to print the titles of what's being run? if($run_object instanceof pts_test_profile) { if($run_object->get_identifier() == null || $run_object->get_title() == null || $this->validate_test_to_run($run_object) == false) { continue; } if($run_contains_a_no_result_type == false && $run_object->get_display_format() == 'NO_RESULT') { $run_contains_a_no_result_type = true; } if($request_results_save == false && $run_object->do_auto_save_results()) { $request_results_save = true; } foreach(self::test_prompts_to_result_objects($run_object) as $result_object) { $this->add_test_result_object($result_object); } } else if($run_object instanceof pts_test_suite) { $this->pre_run_message = $run_object->get_pre_run_message(); $this->post_run_message = $run_object->get_post_run_message(); if($run_object->get_run_mode() == 'PCQS') { $this->is_pcqs = true; } foreach($run_object->get_contained_test_result_objects() as $result_object) { $this->add_test_result_object($result_object); } } else if($run_object instanceof pts_result_file) { // Print the $to_run ? $this->run_description = $run_object->get_description(); $preset_vars = $run_object->get_preset_environment_variables(); $result_objects = $run_object->get_result_objects(); $this->set_save_name($run_object->get_identifier(), false); pts_module_manager::process_environment_variables_string_to_set($preset_vars); foreach($result_objects as &$result_object) { if($result_object->test_profile->get_identifier() == null) { continue; } $test_result = new pts_test_result($result_object->test_profile); $test_result->set_used_arguments($result_object->get_arguments()); $test_result->set_used_arguments_description($result_object->get_arguments_description()); $this->add_test_result_object($test_result); } } else if($run_object instanceof pts_virtual_test_suite) { $virtual_suite_tests = $run_object->get_contained_test_profiles(); foreach(array_keys($virtual_suite_tests) as $i) { if($virtual_suite_tests[$i]->is_supported(false) == false || $this->validate_test_to_run($virtual_suite_tests[$i]) == false) { unset($virtual_suite_tests[$i]); } } sort($virtual_suite_tests); if(count($virtual_suite_tests) > 1) { array_push($virtual_suite_tests, 'All Tests In Suite'); } $run_index = explode(',', pts_user_io::prompt_text_menu('Select the tests in the virtual suite to run', $virtual_suite_tests, true, true)); if(count($virtual_suite_tests) > 2 && in_array((count($virtual_suite_tests) - 1), $run_index)) { // The appended 'All Tests In Suite' was selected, so run all } else { foreach(array_keys($virtual_suite_tests) as $i) { if(!in_array($i, $run_index)) { unset($virtual_suite_tests[$i]); } } } foreach($virtual_suite_tests as &$test_profile) { if($test_profile instanceof pts_test_profile) { // The user is to configure virtual suites manually foreach(self::test_prompts_to_result_objects($test_profile) as $result_object) { $this->add_test_result_object($result_object); } } } } else { pts_client::$display->generic_error($to_run . ' is not recognized.'); continue; } } // AlwaysUploadResultsToOpenBenchmarking AutoSortRunQueue if(pts_config::read_bool_config('PhoronixTestSuite/Options/Testing/AutoSortRunQueue', 'TRUE') && $this->force_save_results == false) { // Not that it matters much, but if $this->force_save_results is set that means likely running from a result file... // so if running a result file, don't change the ordering of the existing results // Sort the run order so that all tests that are similar are grouped together, etc usort($this->tests_to_run, array('pts_test_run_manager', 'cmp_result_object_sort')); } $this->prompt_save_results = $run_contains_a_no_result_type == false || $unique_test_count > 1; $this->force_save_results = $this->force_save_results || $request_results_save; } public static function cmp_result_object_sort($a, $b) { $a_comp = $a->test_profile->get_test_hardware_type() . $a->test_profile->get_test_software_type() . $a->test_profile->get_internal_tags_raw() . $a->test_profile->get_result_scale_formatted() . $a->test_profile->get_identifier(true); $b_comp = $b->test_profile->get_test_hardware_type() . $b->test_profile->get_test_software_type() . $b->test_profile->get_internal_tags_raw() . $b->test_profile->get_result_scale_formatted() . $b->test_profile->get_identifier(true); if($a_comp == $b_comp) { // So it's the same test being compared... try to sort in ascending order (such that 800 x 600 resolution comes before 1024 x 768), below way is an attempt to recognize such in weird manner if(strlen($a->get_arguments_description()) == strlen($b->get_arguments_description())) { return strcmp($a->get_arguments_description(), $b->get_arguments_description()); } else { return strcmp(strlen($a->get_arguments_description()), strlen($b->get_arguments_description())); } } return strcmp($a_comp, $b_comp); } public static function test_profile_system_compatibility_check(&$test_profile, $report_errors = false) { $valid_test_profile = true; $test_type = $test_profile->get_test_hardware_type(); $skip_tests = pts_client::read_env('SKIP_TESTS') ? pts_strings::comma_explode(pts_client::read_env('SKIP_TESTS')) : false; $only_test_types = ($e = pts_client::read_env('ONLY_TEST_TYPES')) ? pts_strings::comma_explode($e) : false; $display_driver = phodevi::read_property('system', 'display-driver'); $gpu = phodevi::read_name('gpu'); if($test_profile->is_supported(false) == false) { $valid_test_profile = false; } else if($test_type == 'Graphics' && pts_client::read_env('DISPLAY') == false && phodevi::is_windows() == false && phodevi::is_macosx() == false) { $report_errors && pts_client::$display->test_run_error('No display server was found, cannot run ' . $test_profile); $valid_test_profile = false; } else if($test_type == 'Graphics' && in_array($display_driver, array('vesa', 'nv', 'cirrus')) && stripos($gpu, 'LLVM') === false) { // These display drivers end up being in known configurations without 3D hardware support so unless an LLVM-based string is reported as the GPU, don't advertise 3D tests $report_errors && pts_client::$display->test_run_error('3D acceleration support not available, cannot run ' . $test_profile); $valid_test_profile = false; } else if($test_type == 'Disk' && stripos(phodevi::read_property('system', 'filesystem'), 'SquashFS') !== false) { $report_errors && pts_client::$display->test_run_error('Running on a RAM-based live file-system, cannot run ' . $test_profile); $valid_test_profile = false; } else if(pts_client::read_env('NO_' . strtoupper($test_type) . '_TESTS') ||($skip_tests && (in_array($test_profile, $skip_tests) || in_array($test_type, $skip_tests) || in_array($test_profile->get_identifier(false), $skip_tests) || in_array($test_profile->get_identifier_base_name(), $skip_tests)))) { $report_errors && pts_client::$display->test_run_error('Due to a pre-set environmental variable, skipping ' . $test_profile); $valid_test_profile = false; } else if($only_test_types && !in_array($test_profile->get_test_hardware_type(), $only_test_types)) { $report_errors && pts_client::$display->test_run_error('Due to a pre-set environmental variable, skipping ' . $test_profile); $valid_test_profile = false; } else if($test_profile->is_root_required() && (pts_c::$test_flags & pts_c::batch_mode) && phodevi::is_root() == false) { $report_errors && pts_client::$display->test_run_error('Cannot run ' . $test_profile . ' in batch mode as root access is required.'); $valid_test_profile = false; } if($valid_test_profile == false && pts_client::read_env('SKIP_ALL_TEST_SUPPORT_CHECKS')) { $report_errors && pts_client::$display->test_run_error('SKIP_ALL_TEST_SUPPORT_CHECKS is set for ' . $test_profile . '.'); $valid_test_profile = true; } return $valid_test_profile; } protected function validate_test_to_run(&$test_profile) { static $test_checks = null; if(!isset($test_checks[$test_profile->get_identifier()])) { $valid_test_profile = true; if(self::test_profile_system_compatibility_check($test_profile, true) == false) { $valid_test_profile = false; } else if($test_profile->get_test_executable_dir() == null) { pts_client::$display->test_run_error('The test executable for ' . $test_profile . ' could not be located.'); $valid_test_profile = false; } if($valid_test_profile && $this->allow_sharing_of_results && $test_profile->allow_results_sharing() == false) { $this->allow_sharing_of_results = false; } $test_checks[$test_profile->get_identifier()] = $valid_test_profile; } return $test_checks[$test_profile->get_identifier()]; } public static function standard_run($to_run, $test_flags = 0) { if(pts_test_run_manager::initial_checks($to_run, $test_flags) == false) { return false; } $test_run_manager = new pts_test_run_manager($test_flags); // Load the tests to run if($test_run_manager->load_tests_to_run($to_run) == false) { return false; } // Save results? $test_run_manager->save_results_prompt(); // Run the actual tests $test_run_manager->pre_execution_process(); $test_run_manager->call_test_runs(); $test_run_manager->post_execution_process(); return $test_run_manager; } } ?> phoronix-test-suite/pts-core/objects/client/pts_tests.php0000644000175000017500000002762712206661345024045 0ustar michaelmichael. */ class pts_tests { public static function installed_tests() { $cleaned_tests = array(); foreach(pts_file_io::glob(pts_client::test_install_root_path() . '*') as $repo_path) { $repo = basename($repo_path); foreach(pts_file_io::glob($repo_path . '/*') as $identifier_path) { if(is_file($identifier_path . '/pts-install.xml')) { $identifier = basename($identifier_path); array_push($cleaned_tests, $repo . '/' . $identifier); } } } return $cleaned_tests; } public static function scan_for_error($log_file, $strip_string) { $error = null; foreach(array('fatal error', 'error:', 'error while loading', 'undefined reference', 'returned 1 exit status', 'not found', 'child process excited with status', 'error opening archive') as $error_string) { if(($e = strripos($log_file, $error_string)) !== false) { if(($line_end = strpos($log_file, PHP_EOL, $e)) !== false) { $log_file = substr($log_file, 0, $line_end); } if(($line_start_e = strrpos($log_file, PHP_EOL)) !== false) { $log_file = substr($log_file, ($line_start_e + 1)); } $log_file = str_replace(array(PTS_TEST_PROFILE_PATH, $strip_string), null, $log_file); if(isset($log_file[8]) && !isset($log_file[144]) && strpos($log_file, PHP_EOL) === false) { $error = $log_file; } } } if($error == null && ($s = strrpos($log_file, PHP_EOL)) !== false && stripos($log_file, 'found', $s) !== false && stripos($log_file, 'no', ($s - 1)) !== false) { // See if the last line of the log is e.g. 'No OpenCL Environment Found', 'FFFFF Not Found', Etc $last_line = trim(substr($log_file, $s)); if(isset($last_line[8]) && !isset($last_line[144])) { $error = $last_line; } } return $error; } public static function pretty_error_string($error) { if(($t = strpos($error, '.h: No such file')) !== false) { $pretty_error = substr($error, strrpos($error, ' ', (0 - (strlen($error) - $t)))); $pretty_error = substr($pretty_error, 0, strpos($pretty_error, ':')); if(isset($pretty_error[2])) { $error = 'Missing Header File: ' . trim($pretty_error); } } else if(($t = strpos($error, 'configure: error: ')) !== false) { $pretty_error = substr($error, ($t + strlen('configure: error: '))); if(($t = strpos($pretty_error, 'not found.')) !== false) { $pretty_error = substr($pretty_error, 0, ($t + strlen('not found.'))); } $error = $pretty_error; } else if(($t = strpos($error, ': not found')) !== false) { $pretty_error = substr($error, 0, $t); $pretty_error = substr($pretty_error, (strrpos($pretty_error, ' ') + 1)); $error = 'Missing Command: ' . $pretty_error; } if(($x = strpos($error, 'See docs')) !== false) { $error = substr($error, 0, $x); } return trim($error); } public static function extra_environmental_variables(&$test_profile) { $extra_vars = array(); $extra_vars['HOME'] = $test_profile->get_install_dir(); $extra_vars['PATH'] = "\$PATH"; $extra_vars['LC_ALL'] = ''; $extra_vars['LC_NUMERIC'] = ''; $extra_vars['LC_CTYPE'] = ''; $extra_vars['LC_MESSAGES'] = ''; $extra_vars['LANG'] = ''; $extra_vars['vblank_mode'] = '0'; $extra_vars['PHP_BIN'] = PHP_BIN; foreach($test_profile->extended_test_profiles() as $i => $this_test_profile) { if($i == 0) { $extra_vars['TEST_EXTENDS'] = $this_test_profile->get_install_dir(); } if(is_dir($this_test_profile->get_install_dir())) { $extra_vars['PATH'] = $this_test_profile->get_install_dir() . ':' . $extra_vars['PATH']; $extra_vars['TEST_' . strtoupper(str_replace('-', '_', $this_test_profile->get_identifier_base_name()))] = $this_test_profile->get_install_dir(); } } return $extra_vars; } public static function call_test_script($test_profile, $script_name, $print_string = null, $pass_argument = null, $extra_vars_append = null, $use_ctp = true) { $extra_vars = pts_tests::extra_environmental_variables($test_profile); if(isset($extra_vars_append['PATH'])) { // Special case variable where you likely want the two merged rather than overwriting $extra_vars['PATH'] = $extra_vars_append['PATH'] . (substr($extra_vars_append['PATH'], -1) != ':' ? ':' : null) . $extra_vars['PATH']; unset($extra_vars_append['PATH']); } if(is_array($extra_vars_append)) { $extra_vars = array_merge($extra_vars, $extra_vars_append); } // TODO: call_test_script could be better cleaned up to fit more closely with new pts_test_profile functions $result = null; $test_directory = $test_profile->get_install_dir(); pts_file_io::mkdir($test_directory, 0777, true); $os_postfix = '_' . strtolower(phodevi::operating_system()); $test_profiles = array($test_profile); if($use_ctp) { $test_profiles = array_merge($test_profiles, $test_profile->extended_test_profiles()); } foreach($test_profiles as &$this_test_profile) { $test_resources_location = $this_test_profile->get_resource_dir(); if(is_file(($run_file = $test_resources_location . $script_name . $os_postfix . '.sh')) || is_file(($run_file = $test_resources_location . $script_name . '.sh'))) { if(!empty($print_string)) { pts_client::$display->test_run_message($print_string); } if(phodevi::is_windows() || pts_client::read_env('USE_PHOROSCRIPT_INTERPRETER') != false) { $phoroscript = new pts_phoroscript_interpreter($run_file, $extra_vars, $test_directory); $phoroscript->execute_script($pass_argument); $this_result = null; } else { $this_result = pts_client::shell_exec('cd ' . $test_directory . ' && sh ' . $run_file . ' "' . $pass_argument . '" 2>&1', $extra_vars); } if(trim($this_result) != null) { $result = $this_result; } } } return $result; } public static function update_test_install_xml(&$test_profile, $this_duration = 0, $is_install = false, $compiler_data = null) { // Refresh/generate an install XML for pts-install.xml if($test_profile->test_installation == false) { // XXX: Hackish way to avoid problems until this function is better written for clean installations, etc $test_profile->test_installation = new pts_installed_test($test_profile); } $xml_writer = new nye_XmlWriter('file://' . PTS_USER_PATH . 'xsl/' . 'pts-test-installation-viewer.xsl'); $test_duration = $test_profile->test_installation->get_average_run_time(); if(!is_numeric($test_duration) && !$is_install) { $test_duration = $this_duration; } if(!$is_install && is_numeric($this_duration) && $this_duration > 0) { $test_duration = ceil((($test_duration * $test_profile->test_installation->get_run_count()) + $this_duration) / ($test_profile->test_installation->get_run_count() + 1)); } $compiler_data = $is_install ? $compiler_data : $test_profile->test_installation->get_compiler_data(); $test_version = $is_install ? $test_profile->get_test_profile_version() : $test_profile->test_installation->get_installed_version(); $test_checksum = $is_install ? $test_profile->get_installer_checksum() : $test_profile->test_installation->get_installed_checksum(); $sys_identifier = $is_install ? phodevi::system_id_string() : $test_profile->test_installation->get_installed_system_identifier(); $install_time = $is_install ? date('Y-m-d H:i:s') : $test_profile->test_installation->get_install_date_time(); $install_time_length = $is_install ? $this_duration : $test_profile->test_installation->get_latest_install_time(); $latest_run_time = $is_install || $this_duration == 0 ? $test_profile->test_installation->get_latest_run_time() : $this_duration; $times_run = $test_profile->test_installation->get_run_count(); if($is_install) { $last_run = $latest_run_time; if(empty($last_run)) { $last_run = '0000-00-00 00:00:00'; } } else { $last_run = date('Y-m-d H:i:s'); $times_run++; } $xml_writer->addXmlNode('PhoronixTestSuite/TestInstallation/Environment/Identifier', $test_profile->get_identifier()); $xml_writer->addXmlNode('PhoronixTestSuite/TestInstallation/Environment/Version', $test_version); $xml_writer->addXmlNode('PhoronixTestSuite/TestInstallation/Environment/CheckSum', $test_checksum); $xml_writer->addXmlNode('PhoronixTestSuite/TestInstallation/Environment/CompilerData', json_encode($compiler_data)); $xml_writer->addXmlNode('PhoronixTestSuite/TestInstallation/Environment/SystemIdentifier', $sys_identifier); $xml_writer->addXmlNode('PhoronixTestSuite/TestInstallation/History/InstallTime', $install_time); $xml_writer->addXmlNode('PhoronixTestSuite/TestInstallation/History/InstallTimeLength', $install_time_length); $xml_writer->addXmlNode('PhoronixTestSuite/TestInstallation/History/LastRunTime', $last_run); $xml_writer->addXmlNode('PhoronixTestSuite/TestInstallation/History/TimesRun', $times_run); $xml_writer->addXmlNode('PhoronixTestSuite/TestInstallation/History/AverageRunTime', $test_duration); $xml_writer->addXmlNode('PhoronixTestSuite/TestInstallation/History/LatestRunTime', $latest_run_time); $xml_writer->saveXMLFile($test_profile->get_install_dir() . 'pts-install.xml'); } public static function invalid_command_helper($passed_args) { $showed_recent_results = pts_test_run_manager::recently_saved_test_results(); if(!empty($passed_args)) { $arg_soundex = soundex($passed_args); $similar_tests = array(); foreach(pts_openbenchmarking::linked_repositories() as $repo) { $repo_index = pts_openbenchmarking::read_repository_index($repo); foreach(array('tests', 'suites') as $type) { if(isset($repo_index[$type]) && is_array($repo_index[$type])) { foreach(array_keys($repo_index[$type]) as $identifier) { if(soundex($identifier) == $arg_soundex) { array_push($similar_tests, array('- ' . $repo . '/' . $identifier, ' [' . ucwords(substr($type, 0, -1)) . ']')); } } } } } foreach(pts_client::saved_test_results() as $result) { if(soundex($result) == $arg_soundex) { array_push($similar_tests, array('- ' . $result, ' [Test Result]')); } } if(count($similar_tests) > 0) { echo 'Possible Suggestions:' . PHP_EOL; if(isset($similar_tests[12])) { // lots of tests... trim it down $similar_tests = array_rand($similar_tests, 12); } echo pts_user_io::display_text_table($similar_tests) . PHP_EOL . PHP_EOL; } } if($showed_recent_results == false) { echo 'See available tests to run by visiting OpenBenchmarking.org or running:' . PHP_EOL . PHP_EOL; echo ' phoronix-test-suite list-tests' . PHP_EOL . PHP_EOL; echo 'Tests can be installed by running:' . PHP_EOL . PHP_EOL; echo ' phoronix-test-suite install ' . PHP_EOL; } } public static function recently_saved_results() { $recent_results = array(); foreach(pts_file_io::glob(PTS_SAVE_RESULTS_PATH . '*/composite.xml') as $composite) { $recent_results[filemtime($composite)] = basename(dirname($composite)); } if(count($recent_results) > 0) { krsort($recent_results); $recent_results = array_slice($recent_results, 0, 6, true); echo PHP_EOL . 'Recently Saved Test Results:' . PHP_EOL; echo pts_user_io::display_text_list($recent_results) . PHP_EOL; return true; } } } ?> phoronix-test-suite/pts-core/objects/client/pts_client.php0000644000175000017500000014174512202327453024152 0ustar michaelmichael. */ class pts_client { public static $display; private static $current_command = null; protected static $lock_pointers = null; public static function create_lock($lock_file) { if(isset(self::$lock_pointers[$lock_file]) || is_writable(dirname($lock_file)) == false || disk_free_space(dirname($lock_file)) < 1024) { return false; } self::$lock_pointers[$lock_file] = fopen($lock_file, 'w'); chmod($lock_file, 0644); return self::$lock_pointers[$lock_file] != false && flock(self::$lock_pointers[$lock_file], LOCK_EX | LOCK_NB); } public static function init() { pts_define_directories(); // Define directories if(function_exists('cli_set_process_title')) { cli_set_process_title('Phoronix Test Suite'); } if(QUICK_START) { return true; } self::basic_init_process(); // Initalize common / needed PTS start-up work pts_network::client_startup(); self::core_storage_init_process(); if(!is_file(PTS_TEMP_STORAGE)) { self::build_temp_cache(); } pts_config::init_files(); pts_define('PTS_TEST_INSTALL_DEFAULT_PATH', pts_client::parse_home_directory(pts_config::read_user_config('PhoronixTestSuite/Options/Installation/EnvironmentDirectory', '~/.phoronix-test-suite/installed-tests/'))); pts_define('PTS_SAVE_RESULTS_PATH', pts_client::parse_home_directory(pts_config::read_user_config('PhoronixTestSuite/Options/Testing/ResultsDirectory', '~/.phoronix-test-suite/test-results/'))); self::extended_init_process(); $openbenchmarking = pts_storage_object::read_from_file(PTS_CORE_STORAGE, 'openbenchmarking'); if($openbenchmarking != null) { // OpenBenchmarking.org Account pts_openbenchmarking_client::init_account($openbenchmarking); } return true; } public static function module_framework_init() { // Process initially called when PTS starts up // Check for modules to auto-load from the configuration file $load_modules = pts_config::read_user_config('PhoronixTestSuite/Options/Modules/LoadModules', null); if(!empty($load_modules)) { foreach(pts_strings::comma_explode($load_modules) as $module) { $module_r = pts_strings::trim_explode('=', $module); if(count($module_r) == 2) { // TODO: end up hooking this into pts_module::read_variable() rather than using the real env pts_client::set_environment_variable($module_r[0], $module_r[1]); } else { pts_module_manager::attach_module($module); } } } // Check for modules to load manually in PTS_MODULES if(($load_modules = pts_client::read_env('PTS_MODULES')) !== false) { foreach(pts_strings::comma_explode($load_modules) as $module) { if(!pts_module_manager::is_module_attached($module)) { pts_module_manager::attach_module($module); } } } // Detect modules to load automatically pts_module_manager::detect_modules_to_load(); // Clean-up modules list pts_module_manager::clean_module_list(); // Reset counter pts_module_manager::set_current_module(null); // Load the modules $module_store_list = array(); foreach(pts_module_manager::attached_modules() as $module) { $class_vars = get_class_vars($module); $module_store_vars = isset($class_vars['module_store_vars']) ? $class_vars['module_store_vars'] : null; if(is_array($module_store_vars)) { foreach($module_store_vars as $store_var) { if(!in_array($store_var, $module_store_list)) { array_push($module_store_list, $store_var); } } } } // Should any of the module options be saved to the results? foreach($module_store_list as $var) { $var_value = pts_client::read_env($var); if(!empty($var_value)) { pts_module_manager::var_store_add($var, $var_value); } } pts_module_manager::module_process('__startup'); pts_define('PTS_STARTUP_TASK_PERFORMED', true); register_shutdown_function(array('pts_module_manager', 'module_process'), '__shutdown'); } public static function open_basedir_check() { $passes = true; $open_basedir = ini_get('open_basedir'); if($open_basedir != false) { $is_in_allowed_dir = false; foreach(explode(':', $open_basedir) as $allowed_dir) { if(strpos(PTS_PATH, $allowed_dir) === 0) { $is_in_allowed_dir = true; break; } } if($is_in_allowed_dir == false) { $passes = false; } } return $passes; } public static function environmental_variables() { // The PTS environmental variables passed during the testing process, etc static $env_variables = null; if($env_variables == null) { $env_variables = array( 'PTS_VERSION' => PTS_VERSION, 'PTS_CODENAME' => PTS_CODENAME, 'PTS_DIR' => PTS_PATH, 'PHP_BIN' => PHP_BIN, 'NUM_CPU_CORES' => phodevi::read_property('cpu', 'core-count'), 'NUM_CPU_JOBS' => (phodevi::read_property('cpu', 'core-count') * 2), 'SYS_MEMORY' => phodevi::read_property('memory', 'capacity'), 'VIDEO_MEMORY' => phodevi::read_property('gpu', 'memory-capacity'), 'VIDEO_WIDTH' => pts_arrays::first_element(phodevi::read_property('gpu', 'screen-resolution')), 'VIDEO_HEIGHT' => pts_arrays::last_element(phodevi::read_property('gpu', 'screen-resolution')), 'VIDEO_MONITOR_COUNT' => phodevi::read_property('monitor', 'count'), 'VIDEO_MONITOR_LAYOUT' => phodevi::read_property('monitor', 'layout'), 'VIDEO_MONITOR_SIZES' => phodevi::read_property('monitor', 'modes'), 'OPERATING_SYSTEM' => phodevi::read_property('system', 'vendor-identifier'), 'OS_VERSION' => phodevi::read_property('system', 'os-version'), 'OS_ARCH' => phodevi::read_property('system', 'kernel-architecture'), 'OS_TYPE' => phodevi::operating_system(), 'THIS_RUN_TIME' => PTS_INIT_TIME, 'DEBUG_REAL_HOME' => pts_client::user_home_directory() ); if(!pts_client::executable_in_path('cc') && pts_client::executable_in_path('gcc')) { // This helps some test profiles build correctly if they don't do a cc check internally $env_variables['CC'] = 'gcc'; } } return $env_variables; } public static function test_install_root_path() { if(getenv('PTS_TEST_INSTALL_ROOT_PATH') != false && is_dir(getenv('PTS_TEST_INSTALL_ROOT_PATH')) && is_writable(getenv('PTS_TEST_INSTALL_ROOT_PATH'))) { return getenv('PTS_TEST_INSTALL_ROOT_PATH'); } else { return PTS_TEST_INSTALL_DEFAULT_PATH; } } public static function user_run_save_variables() { static $runtime_variables = null; if($runtime_variables == null) { $runtime_variables = array( 'VIDEO_RESOLUTION' => phodevi::read_property('gpu', 'screen-resolution-string'), 'VIDEO_CARD' => phodevi::read_name('gpu'), 'VIDEO_DRIVER' => phodevi::read_property('system', 'display-driver-string'), 'OPENGL_DRIVER' => str_replace('(', '', phodevi::read_property('system', 'opengl-driver')), 'OPERATING_SYSTEM' => phodevi::read_property('system', 'operating-system'), 'PROCESSOR' => phodevi::read_name('cpu'), 'MOTHERBOARD' => phodevi::read_name('motherboard'), 'CHIPSET' => phodevi::read_name('chipset'), 'KERNEL_VERSION' => phodevi::read_property('system', 'kernel'), 'COMPILER' => phodevi::read_property('system', 'compiler'), 'HOSTNAME' => phodevi::read_property('system', 'hostname') ); } return $runtime_variables; } public static function save_test_result($save_to = null, $save_results = null, $render_graphs = true, $result_identifier = null) { // Saves PTS result file if(substr($save_to, -4) != '.xml') { $save_to .= '.xml'; } $save_to_dir = pts_client::setup_test_result_directory($save_to); if($save_to == null || $save_results == null) { $bool = false; } else { $save_name = basename($save_to, '.xml'); if($save_name == 'composite' && $render_graphs) { pts_client::generate_result_file_graphs($save_results, $save_to_dir); } $bool = file_put_contents(PTS_SAVE_RESULTS_PATH . $save_to, $save_results); if($result_identifier != null && (pts_config::read_bool_config('PhoronixTestSuite/Options/Testing/SaveSystemLogs', 'TRUE') || (pts_c::$test_flags & pts_c::batch_mode) || (pts_c::$test_flags & pts_c::auto_mode))) { // Save verbose system information here $system_log_dir = $save_to_dir . '/system-logs/' . $result_identifier . '/'; pts_file_io::mkdir($system_log_dir, 0777, true); // Backup system files // TODO: move out these files/commands to log out to respective Phodevi components so only what's relevant will be logged $system_log_files = array( '/var/log/Xorg.0.log', '/proc/cpuinfo', '/proc/meminfo', '/proc/modules', '/proc/mounts', '/proc/cmdline', '/proc/version', '/etc/X11/xorg.conf', '/sys/kernel/debug/dri/0/radeon_pm_info', '/sys/kernel/debug/dri/0/i915_capabilities', '/sys/kernel/debug/dri/0/i915_cur_delayinfo', '/sys/kernel/debug/dri/0/i915_drpc_info', '/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies', ); /* if(phodevi::is_linux()) { // the kernel config file might just be too large to upload for now array_push($system_log_files, '/boot/config-' . php_uname('r')); } */ foreach($system_log_files as $file) { if(is_file($file) && is_readable($file)) { // copy() can't be used in this case since it will result in a blank file for /proc/ file-system $file_contents = file_get_contents($file); $file_contents = pts_strings::remove_line_timestamps($file_contents); file_put_contents($system_log_dir . basename($file), $file_contents); } } // Generate logs from system commands to backup $system_log_commands = array( 'lspci -mmkvvvnn', 'lscpu', 'cc -v', 'lsusb', 'lsmod', 'sensors', 'dmesg', 'vdpauinfo', 'cpufreq-info', 'glxinfo', 'clinfo', 'uname -a', // 'udisks --dump', 'upower --dump', ); if(phodevi::is_bsd()) { array_push($system_log_commands, 'sysctl -a'); array_push($system_log_commands, 'kenv'); } if(is_readable('/dev/mem')) { array_push($system_log_commands, 'dmidecode'); } foreach($system_log_commands as $command_string) { $command = explode(' ', $command_string); if(($command_bin = pts_client::executable_in_path($command[0]))) { $cmd_output = shell_exec('cd ' . dirname($command_bin) . ' && ./' . $command_string . ' 2>&1'); // Try to filter out any serial numbers, etc. phodevi_vfs::cleanse_file($cmd_output, $command[0]); $cmd_output = pts_strings::remove_line_timestamps($cmd_output); file_put_contents($system_log_dir . $command[0], $cmd_output); } } // Dump some common / important environmental variables $environment_variables = array( 'PATH' => null, 'CFLAGS' => null, 'CXXFLAGS' => null, 'LD_LIBRARY_PATH' => null, 'CC' => null, 'CXX' => null, 'LIBGL_DRIVERS_PATH' => null ); foreach($environment_variables as $variable => &$value) { $v = getenv($variable); if($v != null) { $value = $v; } else { unset($environment_variables[$variable]); } } if(!empty($environment_variables)) { $variable_dump = null; foreach($environment_variables as $variable => $value) { $variable_dump .= $variable . '=' . $value . PHP_EOL; } file_put_contents($system_log_dir . 'environment-variables', $variable_dump); } } } return $bool; } public static function save_result_file(&$result_file_writer, $save_name) { // Save the test file // TODO: clean this up with pts_client::save_test_result $j = 1; while(is_file(PTS_SAVE_RESULTS_PATH . $save_name . '/test-' . $j . '.xml')) { $j++; } $real_name = $save_name . '/test-' . $j . '.xml'; pts_client::save_test_result($real_name, $result_file_writer->get_xml()); if(!is_file(PTS_SAVE_RESULTS_PATH . $save_name . '/composite.xml')) { pts_client::save_test_result($save_name . '/composite.xml', file_get_contents(PTS_SAVE_RESULTS_PATH . $real_name), true, $result_file_writer->get_result_identifier()); } else { // Merge Results $merged_results = pts_merge::merge_test_results(file_get_contents(PTS_SAVE_RESULTS_PATH . $save_name . '/composite.xml'), file_get_contents(PTS_SAVE_RESULTS_PATH . $real_name)); pts_client::save_test_result($save_name . '/composite.xml', $merged_results, true, $result_file_writer->get_result_identifier()); } return $real_name; } private static function basic_init_process() { // Initialize The Phoronix Test Suite // PTS Defines pts_define('PHP_BIN', pts_client::read_env('PHP_BIN')); pts_define('PTS_INIT_TIME', time()); if(!defined('PHP_VERSION_ID')) { // PHP_VERSION_ID is only available in PHP 5.2.6 and later $php_version = explode('.', PHP_VERSION); pts_define('PHP_VERSION_ID', ($php_version[0] * 10000 + $php_version[1] * 100 + $php_version[2])); } $dir_init = array(PTS_USER_PATH); foreach($dir_init as $dir) { pts_file_io::mkdir($dir); } } public static function init_display_mode($flags = 0) { $env_mode = ($flags & pts_c::debug_mode) ? 'BASIC' : false; switch(($env_mode != false || ($env_mode = pts_client::read_env('PTS_DISPLAY_MODE')) != false ? $env_mode : pts_config::read_user_config('PhoronixTestSuite/Options/General/DefaultDisplayMode', 'DEFAULT'))) { case 'BASIC': self::$display = new pts_basic_display_mode(); break; case 'BATCH': case 'CONCISE': self::$display = new pts_concise_display_mode(); break; case 'DEFAULT': default: self::$display = new pts_concise_display_mode(); break; } } private static function extended_init_process() { // Extended Initalization Process $directory_check = array( PTS_TEST_INSTALL_DEFAULT_PATH, PTS_SAVE_RESULTS_PATH, PTS_MODULE_LOCAL_PATH, PTS_MODULE_DATA_PATH, PTS_DOWNLOAD_CACHE_PATH, PTS_OPENBENCHMARKING_SCRATCH_PATH, PTS_TEST_PROFILE_PATH, PTS_TEST_SUITE_PATH, PTS_TEST_PROFILE_PATH . 'local/', PTS_TEST_SUITE_PATH . 'local/' ); foreach($directory_check as $dir) { pts_file_io::mkdir($dir); } // Setup PTS Results Viewer pts_file_io::mkdir(PTS_SAVE_RESULTS_PATH . 'pts-results-viewer'); foreach(pts_file_io::glob(PTS_RESULTS_VIEWER_PATH . '*') as $result_viewer_file) { copy($result_viewer_file, PTS_SAVE_RESULTS_PATH . 'pts-results-viewer/' . basename($result_viewer_file)); } copy(PTS_CORE_STATIC_PATH . 'images/pts-106x55.png', PTS_SAVE_RESULTS_PATH . 'pts-results-viewer/pts-106x55.png'); // Setup ~/.phoronix-test-suite/xsl/ pts_file_io::mkdir(PTS_USER_PATH . 'xsl/'); copy(PTS_CORE_STATIC_PATH . 'xsl/pts-test-installation-viewer.xsl', PTS_USER_PATH . 'xsl/' . 'pts-test-installation-viewer.xsl'); copy(PTS_CORE_STATIC_PATH . 'xsl/pts-user-config-viewer.xsl', PTS_USER_PATH . 'xsl/' . 'pts-user-config-viewer.xsl'); copy(PTS_CORE_STATIC_PATH . 'images/pts-308x160.png', PTS_USER_PATH . 'xsl/' . 'pts-logo.png'); // pts_compatibility ops here pts_client::init_display_mode(); } public static function program_requirement_checks($only_show_required = false) { $extension_checks = pts_needed_extensions(); $printed_required_header = false; $printed_optional_header = false; foreach($extension_checks as $extension) { if($extension[1] == false) { if($extension[0] == 1) { // Oops, this extension is required if($printed_required_header == false) { echo PHP_EOL . 'The following PHP extensions are REQUIRED by the Phoronix Test Suite:' . PHP_EOL . PHP_EOL; $printed_required_header = true; } } else { if($only_show_required && $printed_required_header == false) { continue; } // This extension is missing but optional if($printed_optional_header == false) { echo PHP_EOL . ($printed_required_header ? null : 'NOTICE: ') . 'The following PHP extensions are OPTIONAL but recommended:' . PHP_EOL . PHP_EOL; $printed_optional_header = true; } } echo sprintf('%-8ls %-30ls' . PHP_EOL, $extension[2], $extension[3]); } } if($printed_required_header || $printed_optional_header) { echo PHP_EOL; if($printed_required_header) { exit; } } } private static function build_temp_cache() { $pso = pts_storage_object::recover_from_file(PTS_TEMP_STORAGE); if($pso == false) { $pso = new pts_storage_object(); } $pso->add_object('environmental_variables_for_modules', pts_module_manager::modules_environmental_variables()); $pso->add_object('command_alias_list', pts_documentation::client_commands_aliases()); $pso->save_to_file(PTS_TEMP_STORAGE); } private static function core_storage_init_process() { $pso = pts_storage_object::recover_from_file(PTS_CORE_STORAGE); if($pso == false) { $pso = new pts_storage_object(true, true); } // OpenBenchmarking.org - GSID $global_gsid = $pso->read_object('global_system_id'); $global_gsid_e = $pso->read_object('global_system_id_e'); $global_gsid_p = $pso->read_object('global_system_id_p'); if(empty($global_gsid) || pts_openbenchmarking::is_valid_gsid_format($global_gsid) == false) { // Global System ID for anonymous uploads, etc $requested_gsid = true; $global_gsid = pts_openbenchmarking_client::request_gsid(); if(is_array($global_gsid)) { $pso->add_object('global_system_id', $global_gsid['gsid']); // GSID $pso->add_object('global_system_id_p', $global_gsid['gsid_p']); // GSID_P $pso->add_object('global_system_id_e', $global_gsid['gsid_e']); // GSID_E pts_define('PTS_GSID', $global_gsid['gsid']); pts_define('PTS_GSID_E', $global_gsid['gsid_e']); } } else if(pts_openbenchmarking::is_valid_gsid_e_format($global_gsid_e) == false || pts_openbenchmarking::is_valid_gsid_e_format($global_gsid_p) == false) { pts_define('PTS_GSID', $global_gsid); $requested_gsid = false; $global_gsid = pts_openbenchmarking_client::retrieve_gsid(); if(is_array($global_gsid)) { $pso->add_object('global_system_id_p', $global_gsid['gsid_p']); // GSID_P $pso->add_object('global_system_id_e', $global_gsid['gsid_e']); // GSID_E pts_define('PTS_GSID_E', $global_gsid['gsid_e']); } } else { pts_define('PTS_GSID', $global_gsid); pts_define('PTS_GSID_E', $global_gsid_e); $requested_gsid = false; } // Last Run Processing $last_core_version = $pso->read_object('last_core_version'); pts_define('FIRST_RUN_ON_PTS_UPGRADE', ($last_core_version != PTS_CORE_VERSION)); if(FIRST_RUN_ON_PTS_UPGRADE || ($pso->read_object('last_php_version') != PTS_PHP_VERSION)) { // Report any missing/recommended extensions self::program_requirement_checks(); } if(FIRST_RUN_ON_PTS_UPGRADE) { if($requested_gsid == false) { pts_openbenchmarking_client::update_gsid(); } pts_client::build_temp_cache(); } $pso->add_object('last_core_version', PTS_CORE_VERSION); // PTS version last run $pso->add_object('last_php_version', PTS_PHP_VERSION); // PHP version last run //$last_pts_version = $pso->read_object('last_pts_version'); // do something here with $last_pts_version if you want that information $pso->add_object('last_pts_version', PTS_VERSION); // PTS version last run // Last Run Processing $last_run = $pso->read_object('last_run_time'); pts_define('IS_FIRST_RUN_TODAY', (substr($last_run, 0, 10) != date('Y-m-d'))); $pso->add_object('last_run_time', date('Y-m-d H:i:s')); // Time PTS was last run // User Agreement Checking $agreement_cs = $pso->read_object('user_agreement_cs'); $pso->add_object('user_agreement_cs', $agreement_cs); // User agreement check-sum // Phodevi Cache Handling $phodevi_cache = $pso->read_object('phodevi_smart_cache'); if($phodevi_cache instanceof phodevi_cache && pts_flags::no_phodevi_cache() == false) { $phodevi_cache = $phodevi_cache->restore_cache(PTS_USER_PATH, PTS_CORE_VERSION); phodevi::set_device_cache($phodevi_cache); if(($external_phodevi_cache = pts_client::read_env('EXTERNAL_PHODEVI_CACHE'))) { if(is_dir($external_phodevi_cache) && is_file($external_phodevi_cache . '/core.pt2so')) { $external_phodevi_cache .= '/core.pt2so'; } if(is_file($external_phodevi_cache)) { $external_phodevi_cache = pts_storage_object::force_recover_from_file($external_phodevi_cache); if($external_phodevi_cache != false) { $external_phodevi_cache = $external_phodevi_cache->read_object('phodevi_smart_cache'); $external_phodevi_cache = $external_phodevi_cache->restore_cache(null, PTS_CORE_VERSION); if($external_phodevi_cache != false) { //unset($external_phodevi_cache['system']['operating-system']); //unset($external_phodevi_cache['system']['vendor-identifier']); phodevi::set_device_cache($external_phodevi_cache); } } } } } // Archive to disk $pso->save_to_file(PTS_CORE_STORAGE); } public static function user_agreement_check($command) { $pso = pts_storage_object::recover_from_file(PTS_CORE_STORAGE); if($pso == false) { return false; } $config_md5 = $pso->read_object('user_agreement_cs'); $current_md5 = md5_file(PTS_PATH . 'pts-core/user-agreement.txt'); if($config_md5 != $current_md5 || pts_config::read_user_config('PhoronixTestSuite/Options/OpenBenchmarking/AnonymousUsageReporting', 'UNKNOWN') == 'UNKNOWN') { $prompt_in_method = pts_client::check_command_for_function($command, 'pts_user_agreement_prompt'); $user_agreement = file_get_contents(PTS_PATH . 'pts-core/user-agreement.txt'); if($prompt_in_method) { $user_agreement_return = call_user_func(array($command, 'pts_user_agreement_prompt'), $user_agreement); if(is_array($user_agreement_return)) { if(count($user_agreement_return) == 3) { list($agree, $usage_reporting, $hwsw_reporting) = $user_agreement_return; } else { $agree = array_shift($user_agreement_return); $usage_reporting = -1; $hwsw_reporting = -1; } } else { $agree = $user_agreement_return; $usage_reporting = -1; $hwsw_reporting = -1; } } if($prompt_in_method == false || $usage_reporting == -1 || $hwsw_reporting == -1) { pts_client::$display->generic_heading('User Agreement'); echo wordwrap($user_agreement, 65); $agree = pts_flags::user_agreement_skip() || pts_user_io::prompt_bool_input('Do you agree to these terms and wish to proceed', true); if(pts_flags::no_openbenchmarking_reporting()) { $usage_reporting = false; $hwsw_reporting = false; } else { $usage_reporting = $agree ? pts_user_io::prompt_bool_input('Enable anonymous usage / statistics reporting', true) : -1; $hwsw_reporting = $agree ? pts_user_io::prompt_bool_input('Enable anonymous statistical reporting of installed software / hardware', true) : -1; } } if($agree) { echo PHP_EOL; $pso->add_object('user_agreement_cs', $current_md5); $pso->save_to_file(PTS_CORE_STORAGE); } else { pts_client::exit_client('In order to run the Phoronix Test Suite, you must agree to the listed terms.'); } pts_config::user_config_generate(array( 'PhoronixTestSuite/Options/OpenBenchmarking/AnonymousUsageReporting' => pts_config::bool_to_string($usage_reporting), 'PhoronixTestSuite/Options/OpenBenchmarking/AnonymousHardwareReporting' => pts_config::bool_to_string($hwsw_reporting), 'PhoronixTestSuite/Options/OpenBenchmarking/AnonymousSoftwareReporting' => pts_config::bool_to_string($hwsw_reporting) )); } } public static function swap_variables($user_str, $replace_call) { if(is_array($replace_call)) { if(count($replace_call) != 2 || method_exists($replace_call[0], $replace_call[1]) == false) { echo PHP_EOL . 'Var Swap With Method Failed.' . PHP_EOL; return $user_str; } } else if(!function_exists($replace_call)) { echo PHP_EOL . 'Var Swap With Function Failed.' . PHP_EOL; return $user_str; } $offset = 0; $replace_call_return = false; while($offset < strlen($user_str) && ($s = strpos($user_str, '$', $offset)) !== false) { $s++; $var_name = substr($user_str, $s, (($e = strpos($user_str, ' ', $s)) == false ? strlen($user_str) : $e) - $s); if($replace_call_return === false) { $replace_call_return = call_user_func($replace_call); } $var_replacement = isset($replace_call_return[$var_name]) ? $replace_call_return[$var_name] : null; if($var_replacement != null) { $user_str = str_replace('$' . $var_name, $var_replacement, $user_str); } else { // echo "\nVariable Swap For $var_name Failed.\n"; } $offset = $s + strlen($var_replacement); } return $user_str; } public static function setup_test_result_directory($save_to) { $save_to_dir = PTS_SAVE_RESULTS_PATH . $save_to; if(strpos(basename($save_to_dir), '.')) { $save_to_dir = dirname($save_to_dir); } if($save_to_dir != '.') { pts_file_io::mkdir($save_to_dir); } file_put_contents($save_to_dir . '/index.html', 'Phoronix Test Suite'); return $save_to_dir; } public static function remove_installed_test(&$test_profile) { pts_file_io::delete($test_profile->get_install_dir(), null, true); } public static function exit_client($string = null, $exit_status = 0) { // Exit the Phoronix Test Suite client pts_define('PTS_EXIT', 1); if($string != null) { echo PHP_EOL . $string . PHP_EOL; } exit($exit_status); } public static function current_user() { // Current system user return ($pts_user = pts_openbenchmarking_client::user_name()) != null ? $pts_user : phodevi::read_property('system', 'username'); } public static function user_home_directory() { // Gets the system user's home directory static $userhome = null; if($userhome == null) { if(function_exists('posix_getpwuid') && function_exists('posix_getuid')) { $userinfo = posix_getpwuid(posix_getuid()); $userhome = $userinfo['dir']; } else if(($home = pts_client::read_env('HOME'))) { $userhome = $home; } else if(($home = pts_client::read_env('HOMEPATH'))) { $userhome = pts_client::read_env('HOMEDRIVE') . $home; } else { echo PHP_EOL . 'ERROR: Cannot find home directory.' . PHP_EOL; $userhome = null; } $userhome = pts_strings::add_trailing_slash($userhome); } return $userhome; } public static function test_profile_debug_message($message) { $reported = false; if((pts_c::$test_flags & pts_c::debug_mode)) { pts_client::$display->test_run_instance_error($message); $reported = true; } return $reported; } public static function parse_home_directory($path) { // Find home directory if needed if(strpos($path, '~/') !== false) { $path = str_replace('~/', pts_client::user_home_directory(), $path); } return pts_strings::add_trailing_slash($path); } public static function xsl_results_viewer_graph_template() { $raw_xsl = file_get_contents(PTS_RESULTS_VIEWER_PATH . 'pts-results-viewer.xsl'); // System Tables $conversions = array('systems', 'detailed_component', 'radar', 'overview', 'visualize'); foreach($conversions as $convert) { $graph_string = pts_svg_dom::html_embed_code('result-graphs/' . $convert . '.BILDE_EXTENSION', 'SVG', array('width' => 'auto', 'height' => 'auto'), true); $raw_xsl = str_replace('', $graph_string, $raw_xsl); } // Result Graphs $graph_string = pts_svg_dom::html_embed_code('result-graphs/.BILDE_EXTENSION', 'SVG', array('width' => 'auto', 'height' => 'auto'), true); $raw_xsl = str_replace('', $graph_string, $raw_xsl); return $raw_xsl; } public static function generate_result_file_graphs($test_results_identifier, $save_to_dir = false) { if($save_to_dir) { if(pts_file_io::mkdir($save_to_dir . '/result-graphs') == false) { // Directory must exist, so remove any old graph files first foreach(pts_file_io::glob($save_to_dir . '/result-graphs/*') as $old_file) { unlink($old_file); } } } $result_file = new pts_result_file($test_results_identifier); $generated_graphs = array(); $generated_graph_tables = false; // Render overview chart if($save_to_dir) { $chart = new pts_ResultFileTable($result_file); $chart->renderChart($save_to_dir . '/result-graphs/overview.BILDE_EXTENSION'); $intent = -1; if(($intent = pts_result_file_analyzer::analyze_result_file_intent($result_file, $intent, true)) || $result_file->get_system_count() == 1) { $chart = new pts_ResultFileCompactSystemsTable($result_file, $intent); } else { $chart = new pts_ResultFileSystemsTable($result_file); } $chart->renderChart($save_to_dir . '/result-graphs/systems.BILDE_EXTENSION'); unset($chart); if($intent && is_dir($save_to_dir . '/system-logs/')) { $chart = new pts_DetailedSystemComponentTable($result_file, $save_to_dir . '/system-logs/', $intent); if($chart) { $chart->renderChart($save_to_dir . '/result-graphs/detailed_component.BILDE_EXTENSION'); } } } foreach($result_file->get_result_objects() as $key => $result_object) { $save_to = $save_to_dir; if($save_to_dir && is_dir($save_to_dir)) { $save_to .= '/result-graphs/' . ($key + 1) . '.BILDE_EXTENSION'; if(PTS_IS_CLIENT) { if($result_file->is_multi_way_comparison() || pts_client::read_env('GRAPH_GROUP_SIMILAR')) { $table_keys = array(); $titles = $result_file->get_test_titles(); foreach($titles as $this_title_index => $this_title) { if($this_title == $titles[$key]) { array_push($table_keys, $this_title_index); } } } else { $table_keys = $key; } $chart = new pts_ResultFileTable($result_file, null, $table_keys); $chart->renderChart($save_to_dir . '/result-graphs/' . ($key + 1) . '_table.BILDE_EXTENSION'); unset($chart); $generated_graph_tables = true; } } $graph = pts_render::render_graph($result_object, $result_file, $save_to); array_push($generated_graphs, $graph); } // Generate mini / overview graphs if($save_to_dir) { $graph = new pts_OverviewGraph($result_file); if($graph->doSkipGraph() == false) { $graph->renderGraph(); // Check to see if skip_graph was realized during the rendering process if($graph->doSkipGraph() == false) { $graph->svg_dom->output($save_to_dir . '/result-graphs/visualize.BILDE_EXTENSION'); } } unset($graph); $graph = new pts_RadarOverviewGraph($result_file); if($graph->doSkipGraph() == false) { $graph->renderGraph(); // Check to see if skip_graph was realized during the rendering process if($graph->doSkipGraph() == false) { $graph->svg_dom->output($save_to_dir . '/result-graphs/radar.BILDE_EXTENSION'); } } unset($graph); /* // TODO XXX: just stuffing some debug code here temporarily while working on block diagram code... $graph = new pts_BlockDiagramGraph($result_file); $graph->renderGraph(); $graph->svg_dom->output($save_to_dir . '/result-graphs/blocks.BILDE_EXTENSION'); */ } // Save XSL if(count($generated_graphs) > 0 && $save_to_dir) { file_put_contents($save_to_dir . '/pts-results-viewer.xsl', pts_client::xsl_results_viewer_graph_template($generated_graph_tables)); } return $generated_graphs; } public static function process_shutdown_tasks() { // TODO: possibly do something like posix_getpid() != pts_client::$startup_pid in case shutdown function is called from a child process // Generate Phodevi Smart Cache if(pts_flags::no_phodevi_cache() == false && pts_client::read_env('EXTERNAL_PHODEVI_CACHE') == false) { if(pts_config::read_bool_config('PhoronixTestSuite/Options/General/UsePhodeviCache', 'TRUE')) { pts_storage_object::set_in_file(PTS_CORE_STORAGE, 'phodevi_smart_cache', phodevi::get_phodevi_cache_object(PTS_USER_PATH, PTS_CORE_VERSION)); } else { pts_storage_object::set_in_file(PTS_CORE_STORAGE, 'phodevi_smart_cache', null); } } if(is_array(self::$lock_pointers)) { foreach(array_keys(self::$lock_pointers) as $lock_file) { self::release_lock($lock_file); } } } public static function do_anonymous_usage_reporting() { return pts_config::read_bool_config('PhoronixTestSuite/Options/OpenBenchmarking/AnonymousUsageReporting', 0); } public static function release_lock($lock_file) { // Remove lock if(isset(self::$lock_pointers[$lock_file]) == false) { return false; } if(is_resource(self::$lock_pointers[$lock_file])) { fclose(self::$lock_pointers[$lock_file]); } pts_file_io::unlink($lock_file); unset(self::$lock_pointers[$lock_file]); } public static function check_command_for_function($option, $check_function) { $in_option = false; if(is_file(PTS_COMMAND_PATH . $option . '.php')) { if(!class_exists($option, false) && is_file(PTS_COMMAND_PATH . $option . '.php')) { include(PTS_COMMAND_PATH . $option . '.php'); } if(method_exists($option, $check_function)) { $in_option = true; } } return $in_option; } public static function regenerate_graphs($result_file_identifier, $full_process_string = false, $extra_graph_attributes = null) { $save_to_dir = pts_client::setup_test_result_directory($result_file_identifier); $generated_graphs = pts_client::generate_result_file_graphs($result_file_identifier, $save_to_dir, false, $extra_graph_attributes); $generated = count($generated_graphs) > 0; if($generated && $full_process_string) { echo PHP_EOL . $full_process_string . PHP_EOL; pts_client::display_web_page(PTS_SAVE_RESULTS_PATH . $result_file_identifier . '/index.html'); } return $generated; } public static function set_test_flags($test_flags = 0) { pts_c::$test_flags = $test_flags; } public static function execute_command($command, $pass_args = null) { if(!class_exists($command, false) && is_file(PTS_COMMAND_PATH . $command . '.php')) { include(PTS_COMMAND_PATH . $command . '.php'); } if(is_file(PTS_COMMAND_PATH . $command . '.php') && method_exists($command, 'argument_checks')) { $argument_checks = call_user_func(array($command, 'argument_checks')); foreach($argument_checks as &$argument_check) { $function_check = $argument_check->get_function_check(); $method_check = false; if(is_array($function_check) && count($function_check) == 2) { $method_check = $function_check[0]; $function_check = $function_check[1]; } if(substr($function_check, 0, 1) == '!') { $function_check = substr($function_check, 1); $return_fails_on = true; } else { $return_fails_on = false; } if($method_check != false) { if(!method_exists($method_check, $function_check)) { echo PHP_EOL . 'Method check fails.' . PHP_EOL; continue; } $function_check = array($method_check, $function_check); } else if(!function_exists($function_check)) { continue; } if($argument_check->get_argument_index() == 'VARIABLE_LENGTH') { $return_value = null; foreach($pass_args as $arg) { $return_value = call_user_func_array($function_check, array($arg)); if($return_value == true) { break; } } } else { $return_value = call_user_func_array($function_check, array((isset($pass_args[$argument_check->get_argument_index()]) ? $pass_args[$argument_check->get_argument_index()] : null))); } if($return_value == $return_fails_on) { $command_alias = defined($command . '::doc_use_alias') ? constant($command . '::doc_use_alias') : $command; if((isset($pass_args[$argument_check->get_argument_index()]) && !empty($pass_args[$argument_check->get_argument_index()])) || ($argument_check->get_argument_index() == 'VARIABLE_LENGTH' && !empty($pass_args))) { pts_client::$display->generic_error('Invalid Argument: ' . implode(' ', $pass_args)); } else { pts_client::$display->generic_error('Argument Missing.'); } echo 'CORRECT SYNTAX:' . PHP_EOL . 'phoronix-test-suite ' . str_replace('_', '-', $command_alias) . ' ' . implode(' ', $argument_checks) . PHP_EOL . PHP_EOL; if(method_exists($command, 'invalid_command')) { call_user_func_array(array($command, 'invalid_command'), $pass_args); echo PHP_EOL; } return false; } else { if($argument_check->get_function_return_key() != null && !isset($pass_args[$argument_check->get_function_return_key()])) { $pass_args[$argument_check->get_function_return_key()] = $return_value; } } } } pts_module_manager::module_process('__pre_option_process', $command); if(is_file(PTS_COMMAND_PATH . $command . '.php')) { self::$current_command = $command; if(method_exists($command, 'run')) { call_user_func(array($command, 'run'), $pass_args); } else { echo PHP_EOL . 'There is an error in the requested command: ' . $command . PHP_EOL . PHP_EOL; } } else if(($t = pts_module::valid_run_command($command)) != false) { list($module, $module_command) = $t; pts_module_manager::set_current_module($module); pts_module_manager::run_command($module, $module_command, $pass_args); pts_module_manager::set_current_module(null); } echo PHP_EOL; pts_module_manager::module_process('__post_option_process', $command); } public static function current_command() { return self::$current_command; } public static function terminal_width() { static $terminal_width = null; if($terminal_width == null) { $chars = -1; if(pts_client::executable_in_path('tput')) { $terminal_width = trim(shell_exec('tput cols 2>&1')); if(is_numeric($terminal_width) && $terminal_width > 1) { $chars = $terminal_width; } } else if(phodevi::is_windows()) { // Need a better way to handle this $chars = 80; } $terminal_width = $chars; } return $terminal_width; } public static function user_hardware_software_reporting() { $hw_reporting = pts_config::read_bool_config('PhoronixTestSuite/Options/OpenBenchmarking/AnonymousHardwareReporting', 'FALSE'); $sw_reporting = pts_config::read_bool_config('PhoronixTestSuite/Options/OpenBenchmarking/AnonymousSoftwareReporting', 'FALSE'); if($hw_reporting == false && $sw_reporting == false) { return; } $hw = array(); $sw = array(); $pso = pts_storage_object::recover_from_file(PTS_CORE_STORAGE); if($hw_reporting) { $hw = array(); foreach(pts_openbenchmarking::stats_hardware_list() as $key => $value) { if(count($value) == 2) { $hw[$key] = phodevi::read_property($value[0], $value[1]); } else { $hw[$key] = phodevi::read_name($value[0]); } } $hw_prev = $pso->read_object('global_reported_hw'); $pso->add_object('global_reported_hw', $hw); if(is_array($hw_prev)) { $hw = array_diff_assoc($hw, $hw_prev); } // Check the PCI devices $pci = phodevi::read_property('motherboard', 'pci-devices'); $pci_prev = $pso->read_object('global_reported_pci'); $pso->add_object('global_reported_pci', $pci); if(!empty($pci_prev) && is_array($pci_prev) && is_array($pci)) { if($pci == $pci_prev) { $pci = null; } else { $pci = array_diff($pci, $pci_prev); } } if(!empty($pci)) { pts_openbenchmarking_client::upload_pci_data($pci); } // Check the USB devices $usb = phodevi::read_property('motherboard', 'usb-devices'); $usb_prev = $pso->read_object('global_reported_usb'); $pso->add_object('global_reported_usb', $usb); if(!empty($usb_prev) && is_array($usb_prev) && is_array($usb) && $usb != $usb_prev) { pts_openbenchmarking_client::upload_usb_data($usb); } } if($sw_reporting) { $sw = array(); foreach(pts_openbenchmarking::stats_software_list() as $key => $value) { if(count($value) == 2) { $sw[$key] = phodevi::read_property($value[0], $value[1]); } else { $sw[$key] = phodevi::read_name($value[0]); } } $sw_prev = $pso->read_object('global_reported_sw'); $pso->add_object('global_reported_sw', $sw); if(is_array($sw_prev)) { $sw = array_diff_assoc($sw, $sw_prev); } } $to_report = array_merge($hw, $sw); $pso->save_to_file(PTS_CORE_STORAGE); if(!empty($to_report)) { pts_openbenchmarking_client::upload_hwsw_data($to_report); } } public static function is_process_running($process) { if(phodevi::is_linux()) { // Checks if process is running on the system $running = shell_exec('ps -C ' . strtolower($process) . ' 2>&1'); $running = trim(str_replace(array('PID', 'TTY', 'TIME', 'CMD'), '', $running)); } else if(phodevi::is_solaris()) { // Checks if process is running on the system $ps = shell_exec('ps -ef 2>&1'); $running = strpos($ps, ' ' . strtolower($process)) != false ? 'TRUE' : null; } else if(pts_client::executable_in_path('ps') != false) { // Checks if process is running on the system $ps = shell_exec('ps -ax 2>&1'); $running = strpos($ps, ' ' . strtolower($process)) != false ? 'TRUE' : null; } else { $running = null; } return !empty($running); } public static function parse_value_string_double_identifier($value_string) { // i.e. with PRESET_OPTIONS='stream.run-type=Add' $values = array(); foreach(explode(';', $value_string) as $preset) { if(count($preset = pts_strings::trim_explode('=', $preset)) == 2) { if(count($preset[0] = pts_strings::trim_explode('.', $preset[0])) == 2) { $values[$preset[0][0]][$preset[0][1]] = $preset[1]; } } } return $values; } public static function create_temporary_file() { return tempnam(pts_client::temporary_directory(), 'PTS'); } public static function temporary_directory() { if(PHP_VERSION_ID >= 50210) { $dir = sys_get_temp_dir(); } else { $dir = '/tmp'; // Assume /tmp } return $dir; } public static function read_env($var) { return getenv($var); } public static function pts_set_environment_variable($name, $value) { // Sets an environmental variable return getenv($name) == false && putenv($name . '=' . $value); } public static function shell_exec($exec, $extra_vars = null) { // Same as shell_exec() but with the PTS env variables added in // Convert pts_client::environmental_variables() into shell export variable syntax $var_string = ''; $extra_vars = ($extra_vars == null ? pts_client::environmental_variables() : array_merge(pts_client::environmental_variables(), $extra_vars)); foreach(array_keys($extra_vars) as $key) { $var_string .= 'export ' . $key . '=' . $extra_vars[$key] . ';'; } $var_string .= ' '; return shell_exec($var_string . $exec); } public static function executable_in_path($executable) { static $cache = null; if(!isset($cache[$executable])) { $paths = pts_strings::trim_explode((phodevi::is_windows() ? ';' : ':'), (($path = pts_client::read_env('PATH')) == false ? '/usr/bin:/usr/local/bin' : $path)); $executable_path = false; foreach($paths as $path) { $path = pts_strings::add_trailing_slash($path); if(is_executable($path . $executable)) { $executable_path = $path . $executable; break; } } $cache[$executable] = $executable_path; } return $cache[$executable]; } public static function display_web_page($URL, $alt_text = null, $default_open = true, $auto_open = false) { if(((pts_c::$test_flags & pts_c::auto_mode) && $auto_open == false && $default_open == false) || (pts_client::read_env('DISPLAY') == false && phodevi::is_windows() == false && phodevi::is_macosx() == false) || defined('PHOROMATIC_PROCESS')) { return; } if($auto_open == false) { $view_results = pts_user_io::prompt_bool_input(($alt_text == null ? 'Do you want to view the results in your web browser' : $alt_text), $default_open); } else { $view_results = true; } if($view_results) { static $browser = null; if($browser == null) { $config_browser = pts_config::read_user_config('PhoronixTestSuite/Options/General/DefaultBrowser', null); if($config_browser != null && (is_executable($config_browser) || ($config_browser = pts_client::executable_in_path($config_browser)))) { $browser = $config_browser; } else if(phodevi::is_windows()) { $windows_browsers = array( 'C:\Program Files (x86)\Mozilla Firefox\firefox.exe', 'C:\Program Files\Internet Explorer\iexplore.exe' ); foreach($windows_browsers as $browser_test) { if(is_executable($browser_test)) { $browser = $browser_test; break; } } if(substr($URL, 0, 1) == '\\') { $URL = 'file:///C:' . str_replace('/', '\\', $URL); } } else { $possible_browsers = array('epiphany', 'firefox', 'mozilla', 'x-www-browser', 'open', 'xdg-open', 'iceweasel', 'konqueror'); foreach($possible_browsers as &$b) { if(($b = pts_client::executable_in_path($b))) { $browser = $b; break; } } } } if($browser != null) { shell_exec($browser . ' "' . $URL . '" 2> /dev/null &'); } else { echo PHP_EOL . 'No Web Browser Found.' . PHP_EOL; } } } public static function cache_hardware_calls() { phodevi::system_hardware(true); phodevi::supported_sensors(); phodevi::unsupported_sensors(); } public static function cache_software_calls() { phodevi::system_software(true); } public static function remove_saved_result_file($identifier) { pts_file_io::delete(PTS_SAVE_RESULTS_PATH . $identifier, null, true); } public static function saved_test_results() { $results = array(); $ignore_ids = array(); foreach(pts_file_io::glob(PTS_SAVE_RESULTS_PATH . '*/composite.xml') as $result_file) { $identifier = basename(dirname($result_file)); if(!in_array($identifier, $ignore_ids)) { array_push($results, $identifier); } } return $results; } public static function code_error_handler($error_code, $error_string, $error_file, $error_line) { if(($error_code & (E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE))) { // It's a self-generated error by pts-core code intentionally return self::user_error_handler($error_code, $error_string, $error_file, $error_line); } /*if(!(error_reporting() & $error_code)) { return; }*/ switch($error_code) { case E_ERROR: case E_PARSE: $error_type = 'ERROR'; break; case E_WARNING: case E_NOTICE: if(($s = strpos($error_string, 'Undefined ')) !== false && ($x = strpos($error_string, ': ', $s)) !== false) { $error_string = 'Undefined: ' . substr($error_string, ($x + 2)); } else if(strpos($error_string, 'Name or service not known') !== false || strpos($error_string, 'HTTP request failed') !== false || strpos($error_string, 'fopen') !== false || strpos($error_string, 'file_get_contents') !== false || strpos($error_string, 'Directory not empty') !== false) { // Don't report network errors return; } $error_type = 'NOTICE'; break; default: $error_type = $error_code; break; } echo PHP_EOL . '[' . $error_type . '] ' . $error_string . ' in ' . basename($error_file) . ':' . $error_line . PHP_EOL; if($error_type == 'ERROR') { exit(1); } } public static function user_error_handler($error_code, $error_string, $error_file, $error_line) { /* trigger_error('Scheisse', E_USER_WARNING); trigger_error('Okay', E_USER_NOTICE); trigger_error('F', E_USER_ERROR); */ switch($error_code) { case E_USER_ERROR: $error_type = 'ERROR'; break; case E_USER_NOTICE: if(pts_client::is_client_debug_mode() == false) { return; } $error_type = 'NOTICE'; break; case E_USER_WARNING: $error_type = 'NOTICE'; // Yes, report warnings as a notice label break; } echo '[' . $error_type . '] ' . $error_string . (pts_client::is_client_debug_mode() ? ' in ' . basename($error_file) . ':' . $error_line : null) . PHP_EOL; return; } public static function is_client_debug_mode() { return false; // TODO } } // Some extra magic set_error_handler(array('pts_client', 'code_error_handler')); if(PTS_IS_CLIENT && (PTS_IS_DEV_BUILD || pts_client::is_client_debug_mode())) { // Enable more verbose error reporting only when PTS is in development with milestone (alpha/beta) releases but no release candidate (r) or gold versions error_reporting(E_ALL | E_NOTICE | E_STRICT); } ?> phoronix-test-suite/pts-core/objects/client/pts_test_installer.php0000644000175000017500000007607112172337575025743 0ustar michaelmichael. */ class pts_test_installer { public static function standard_install($items_to_install, $test_flags = 0) { // Refresh the pts_client::$display in case we need to run in debug mode pts_client::init_display_mode(); // Create a lock $lock_path = pts_client::temporary_directory() . '/phoronix-test-suite.active'; pts_client::create_lock($lock_path); pts_client::set_test_flags($test_flags); // Get the test profiles $unknown_tests = array(); $test_profiles = pts_types::identifiers_to_test_profile_objects($items_to_install, true, true, $unknown_tests); // Any external dependencies? pts_external_dependencies::install_dependencies($test_profiles); // Install tests if(!is_writable(pts_client::test_install_root_path())) { trigger_error('The test installation directory is not writable.' . PHP_EOL . 'Location: ' . pts_client::test_install_root_path(), E_USER_ERROR); return false; } pts_test_installer::start_install($test_profiles, $unknown_tests); pts_client::release_lock($lock_path); return $test_profiles; } public static function start_install(&$test_profiles, &$unknown_tests = null) { if(count($test_profiles) == 0) { pts_client::$display->generic_error('No Tests Found For Installation.'); return false; } // Setup the install manager and add the tests $test_install_manager = new pts_test_install_manager(); foreach($test_profiles as &$test_profile) { if($test_profile->get_identifier() == null) { continue; } if($test_profile->needs_updated_install()) { if($test_profile->is_supported(false) == false) { pts_client::$display->generic_sub_heading('Not Supported: ' . $test_profile->get_identifier()); } else if($test_install_manager->add_test_profile($test_profile) != false) { pts_client::$display->generic_sub_heading('To Install: ' . $test_profile->get_identifier()); } } else { pts_client::$display->generic_sub_heading('Installed: ' . $test_profile->get_identifier()); } } if($unknown_tests) { foreach($unknown_tests as $unkown) { pts_client::$display->generic_sub_heading('Unknown: ' . $unkown); } } if($test_install_manager->tests_to_install_count() == 0) { return true; } // Let the pts_test_install_manager make some estimations, etc... echo PHP_EOL; $test_install_manager->generate_download_file_lists(); $test_install_manager->check_download_caches_for_files(); pts_client::$display->test_install_process($test_install_manager); // Begin the install process pts_module_manager::module_process('__pre_install_process', $test_install_manager); $failed_installs = array(); $test_profiles = array(); while(($test_install_request = $test_install_manager->next_in_install_queue()) != false) { pts_client::$display->test_install_start($test_install_request->test_profile->get_identifier()); $installed = pts_test_installer::install_test_process($test_install_request); $compiler_data = pts_test_installer::end_compiler_mask($test_install_request); if($installed) { if(pts_client::do_anonymous_usage_reporting() && $test_install_request->install_time_duration > 0) { // If anonymous usage reporting enabled, report install time to OpenBenchmarking.org pts_openbenchmarking_client::upload_usage_data('test_install', array($test_install_request, $test_install_request->install_time_duration)); } pts_tests::update_test_install_xml($test_install_request->test_profile, $test_install_request->install_time_duration, true, $compiler_data); array_push($test_profiles, $test_install_request->test_profile); } else { array_push($failed_installs, $test_install_request); } } pts_module_manager::module_process('__post_install_process', $test_install_manager); pts_download_speed_manager::save_data(); if(count($failed_installs) > 1) { echo PHP_EOL . 'The following tests failed to install:' . PHP_EOL . PHP_EOL; foreach($failed_installs as &$install_request) { echo ' - ' . $install_request->test_profile . PHP_EOL; // If many tests are being installed, show the error messages reported in order to reduce scrolling... if($install_request->install_error && isset($failed_installs[5])) { echo ' [' . $install_request->install_error . ']' . PHP_EOL; } } } } public static function only_download_test_files(&$test_profiles, $to_dir = null) { // Setup the install manager and add the tests $test_install_manager = new pts_test_install_manager(); foreach($test_profiles as &$test_profile) { if($test_install_manager->add_test_profile($test_profile) != false) { pts_client::$display->generic_sub_heading('To Download Files: ' . $test_profile->get_identifier()); } } if($test_install_manager->tests_to_install_count() == 0) { return true; } // Let the pts_test_install_manager make some estimations, etc... $test_install_manager->generate_download_file_lists(); $test_install_manager->check_download_caches_for_files(); // Begin the download process while(($test_install_request = $test_install_manager->next_in_install_queue()) != false) { //pts_client::$display->test_install_start($test_install_request->test_profile->get_identifier()); pts_test_installer::download_test_files($test_install_request, $to_dir); } } protected static function download_test_files(&$test_install_request, $download_location = false) { // Download needed files for a test if($test_install_request->get_download_object_count() == 0) { return true; } $identifier = $test_install_request->test_profile->get_identifier(); pts_client::$display->test_install_downloads($test_install_request); if($download_location == false) { $download_location = $test_install_request->test_profile->get_install_dir(); } pts_file_io::mkdir($download_location); $module_pass = array($identifier, $test_install_request->get_download_objects()); pts_module_manager::module_process('__pre_test_download', $module_pass); foreach($test_install_request->get_download_objects() as $download_package) { $package_filename = $download_package->get_filename(); $package_md5 = $download_package->get_md5(); $package_sha256 = $download_package->get_sha256(); $download_destination = $download_location . $package_filename; $download_destination_temp = $download_destination . '.pts'; if($download_package->get_download_location_type() == null) { // Attempt a possible last-minute look-aside copy cache in case a previous test in the install queue downloaded this file already $lookaside_copy = pts_test_install_manager::file_lookaside_test_installations($package_filename, $package_md5, $package_sha256); if($lookaside_copy) { if($download_package->get_filesize() == 0) { $download_package->set_filesize(filesize($lookaside_copy)); } $download_package->set_download_location('LOOKASIDE_DOWNLOAD_CACHE', array($lookaside_copy)); } } switch($download_package->get_download_location_type()) { case 'IN_DESTINATION_DIR': pts_client::$display->test_install_download_file('FILE_FOUND', $download_package); continue; case 'REMOTE_DOWNLOAD_CACHE': foreach($download_package->get_download_location_path() as $remote_download_cache_file) { pts_client::$display->test_install_download_file('DOWNLOAD_FROM_CACHE', $download_package); pts_network::download_file($remote_download_cache_file, $download_destination_temp); if(pts_test_installer::validate_md5_download_file($download_destination_temp, $package_md5)) { rename($download_destination_temp, $download_destination); continue; } else { pts_client::$display->test_install_error('The check-sum of the downloaded file failed.'); pts_file_io::unlink($download_destination_temp); } } case 'MAIN_DOWNLOAD_CACHE': case 'LOCAL_DOWNLOAD_CACHE': case 'LOOKASIDE_DOWNLOAD_CACHE': $download_cache_file = pts_arrays::last_element($download_package->get_download_location_path()); if(is_file($download_cache_file)) { if((pts_config::read_bool_config('PhoronixTestSuite/Options/Installation/SymLinkFilesFromCache', 'FALSE') && $download_package->get_download_location_type() != 'LOOKASIDE_DOWNLOAD_CACHE') || pts_flags::is_live_cd()) { // For look-aside copies never symlink (unless a pre-packaged LiveCD) in case the other test ends up being un-installed // SymLinkFilesFromCache is disabled by default pts_client::$display->test_install_download_file('LINK_FROM_CACHE', $download_package); symlink($download_cache_file, $download_destination); } else { // File is to be copied // Try up to two times to copy a file $attempted_copies = 0; do { pts_client::$display->test_install_download_file('COPY_FROM_CACHE', $download_package); // $context = stream_context_create(); // stream_context_set_params($context, array('notification' => array('pts_network', 'stream_status_callback'))); // TODO: get the context working correctly for this copy() copy($download_cache_file, $download_destination_temp); pts_client::$display->test_install_progress_completed(); // Verify that the file was copied fine if(pts_test_installer::validate_md5_download_file($download_destination_temp, $package_md5)) { rename($download_destination_temp, $download_destination); break; } else { pts_client::$display->test_install_error('The check-sum of the copied file failed.'); pts_file_io::unlink($download_destination_temp); } $attempted_copies++; } while($attempted_copies < 2); } if(is_file($download_destination)) { continue; } } default: $package_urls = $download_package->get_download_url_array(); // Download the file if(!is_file($download_destination) && count($package_urls) > 0 && $package_urls[0] != null) { $fail_count = 0; do { if((pts_c::$test_flags ^ pts_c::batch_mode) && (pts_c::$test_flags ^ pts_c::auto_mode) && pts_config::read_bool_config('PhoronixTestSuite/Options/Installation/PromptForDownloadMirror', 'FALSE') && count($package_urls) > 1) { // Prompt user to select mirror do { echo PHP_EOL . 'Available Download Mirrors:' . PHP_EOL . PHP_EOL; $url = pts_user_io::prompt_text_menu('Select Preferred Mirror', $package_urls, false); } while(pts_strings::is_url($url) == false); } else { // Auto-select mirror shuffle($package_urls); do { $url = array_pop($package_urls); } while(pts_strings::is_url($url) == false && !empty($package_urls)); } pts_client::$display->test_install_download_file('DOWNLOAD', $download_package); $download_start = time(); pts_network::download_file($url, $download_destination_temp); $download_end = time(); if(pts_test_installer::validate_md5_download_file($download_destination_temp, $package_md5)) { // Download worked if(is_file($download_destination_temp)) { rename($download_destination_temp, $download_destination); } if($download_package->get_filesize() > 0 && $download_end != $download_start) { pts_download_speed_manager::update_download_speed_average($download_package->get_filesize(), ($download_end - $download_start)); } } else { // Download failed if(is_file($download_destination_temp) && filesize($download_destination_temp) > 0) { pts_client::$display->test_install_error('MD5 Failed: ' . $url); $md5_failed = true; } else { pts_client::$display->test_install_error('Download Failed: ' . $url); $md5_failed = false; } pts_file_io::unlink($download_destination_temp); $fail_count++; if($fail_count > 3) { $try_again = false; } else { if(count($package_urls) > 0 && $package_urls[0] != null) { pts_client::$display->test_install_error('Attempting to download from alternate mirror.'); $try_again = true; } else { if((pts_c::$test_flags & pts_c::batch_mode) || (pts_c::$test_flags & pts_c::auto_mode)) { $try_again = false; } else if($md5_failed) { $try_again = pts_user_io::prompt_bool_input('Try downloading the file again', true, 'TRY_DOWNLOAD_AGAIN'); } else { $try_again = false; } if($try_again) { array_push($package_urls, $url); } } } if(!$try_again) { //pts_client::$display->test_install_error('Download of Needed Test Dependencies Failed!'); return false; } } } while(!is_file($download_destination)); } pts_module_manager::module_process('__interim_test_download', $module_pass); } } pts_module_manager::module_process('__post_test_download', $identifier); return true; } public static function create_compiler_mask(&$test_install_request) { // or pass false to $test_install_request to bypass the test checks $compilers = array(); if($test_install_request === false || in_array('build-utilities', $test_install_request->test_profile->get_dependencies())) { // Handle C/C++ compilers for this external dependency $compilers['CC'] = array(pts_strings::first_in_string(pts_client::read_env('CC'), ' '), 'gcc', 'clang', 'icc', 'pcc'); $compilers['CXX'] = array(pts_strings::first_in_string(pts_client::read_env('CXX'), ' '), 'g++', 'clang++', 'cpp'); } if($test_install_request === false || in_array('fortran-compiler', $test_install_request->test_profile->get_dependencies())) { // Handle Fortran for this external dependency $compilers['F9X'] = array(pts_strings::first_in_string(pts_client::read_env('F9X'), ' '), pts_strings::first_in_string(pts_client::read_env('F95'), ' '), 'gfortran', 'f90', 'f95', 'fortran'); } if(empty($compilers)) { // If the test profile doesn't request a compiler external dependency, probably not compiling anything return false; } foreach($compilers as $compiler_type => $possible_compilers) { // Compilers to check for, listed in order of priority $compiler_found = false; foreach($possible_compilers as $i => $possible_compiler) { // first check to ensure not null sent to executable_in_path from env variable if($possible_compiler && (($compiler_path = is_executable($possible_compiler)) || ($compiler_path = pts_client::executable_in_path($possible_compiler)))) { // Replace the array of possible compilers with a string to the detected compiler executable $compilers[$compiler_type] = $compiler_path; $compiler_found = true; break; } } if($compiler_found == false) { unset($compilers[$compiler_type]); } } if(!empty($compilers)) { // Create a temporary directory that will be at front of PATH and serve for masking the actual compiler if($test_install_request instanceof pts_test_install_request) { $mask_dir = pts_client::temporary_directory() . '/pts-compiler-mask-' . $test_install_request->test_profile->get_identifier_base_name() . $test_install_request->test_profile->get_test_profile_version() . '/'; } else { $mask_dir = pts_client::temporary_directory() . '/pts-compiler-mask-' . rand(100, 999) . '/'; } pts_file_io::mkdir($mask_dir); $compiler_extras = array( 'CC' => array('safeguard-names' => array('gcc', 'cc'), 'environment-variables' => 'CFLAGS'), 'CXX' => array('safeguard-names' => array('g++', 'c++'), 'environment-variables' => 'CXXFLAGS'), 'F9X' => array('safeguard-names' => array('gfortran', 'f95'), 'environment-variables' => 'F9XFLAGS') ); foreach($compilers as $compiler_type => $compiler_path) { $compiler_name = basename($compiler_path); $main_compiler = $mask_dir . $compiler_name; // take advantage of environment-variables to be sure they're found in the string $env_var_check = PHP_EOL; /* foreach(pts_arrays::to_array($compiler_extras[$compiler_type]['environment-variables']) as $env_var) { // since it's a dynamic check in script could probably get rid of this check... if(true || getenv($env_var)) { $env_var_check .= 'if [[ $COMPILER_OPTIONS != "*$' . $env_var . '*" ]]' . PHP_EOL . 'then ' . PHP_EOL . 'COMPILER_OPTIONS="$COMPILER_OPTIONS $' . $env_var . '"' . PHP_EOL . 'fi' . PHP_EOL; } } */ // Write the main mask for the compiler file_put_contents($main_compiler, '#!/bin/bash' . PHP_EOL . 'COMPILER_OPTIONS="$@"' . PHP_EOL . $env_var_check . PHP_EOL . 'echo $COMPILER_OPTIONS >> ' . $mask_dir . $compiler_type . '-options-' . $compiler_name . PHP_EOL . $compiler_path . ' "$@"' . PHP_EOL); // Make executable chmod($main_compiler, 0755); // The two below code chunks ensure the proper compiler is always hit if($test_install_request instanceof pts_test_install_request && !in_array($compiler_name, pts_arrays::to_array($compiler_extras[$compiler_type]['safeguard-names'])) && getenv($compiler_type) == false) { // So if e.g. clang becomes the default compiler, since it's not GCC, it will ensure CC is also set to clang beyond the masking below $test_install_request->special_environment_vars[$compiler_type] = $compiler_name; } // Just in case any test profile script is statically always calling 'gcc' or anything not CC, try to make sure it hits one of the safeguard-names so it redirects to the intended compiler under test foreach(pts_arrays::to_array($compiler_extras[$compiler_type]['safeguard-names']) as $safe_name) { if(!is_file($mask_dir . $safe_name)) { symlink($main_compiler, $mask_dir . $safe_name); } } } if($test_install_request instanceof pts_test_install_request) { $test_install_request->compiler_mask_dir = $mask_dir; // Appending the rest of the path will be done automatically within call_test_script $test_install_request->special_environment_vars['PATH'] = $mask_dir; } return $mask_dir; } return false; } public static function end_compiler_mask(&$test_install_request) { if($test_install_request->compiler_mask_dir == false && !is_dir($test_install_request->compiler_mask_dir)) { return false; } $compiler = false; foreach(pts_file_io::glob($test_install_request->compiler_mask_dir . '*-options-*') as $compiler_output) { $output_name = basename($compiler_output); $compiler_type = substr($output_name, 0, strpos($output_name, '-')); $compiler_choice = substr($output_name, (strrpos($output_name, 'options-') + 8)); $compiler_lines = explode(PHP_EOL, pts_file_io::file_get_contents($compiler_output)); // Clean-up / reduce the compiler options that are important $compiler_options = null; $compiler_backup_line = null; foreach($compiler_lines as $l => $compiler_line) { $compiler_line .= ' '; // allows for easier/simplified detection in a few checks below $o = strpos($compiler_line, '-o '); if($o === false) { unset($compiler_lines[$l]); continue; } $o = substr($compiler_line, ($o + 3), (strpos($compiler_line, ' ', ($o + 3)) - $o - 3)); $o_l = strlen($o); // $o now has whatever is set for the -o output if(($o_l > 2 && substr(basename($o), 0, 3) == 'lib') || ($o_l > 3 && substr($o, -4) == 'test')) { // If it's a lib, probably not what is the actual target unset($compiler_lines[$l]); continue; } else if(($o_l > 2 && substr($o, -2) == '.o')) { // If it's outputting to a .o should not be the proper compile command we want // but back it up in case... keep overwriting temp variable to get the last one $compiler_backup_line = $compiler_line; unset($compiler_lines[$l]); continue; } } if(!empty($compiler_lines)) { $compiler_line = array_pop($compiler_lines); if(strpos($compiler_line, '-O') === false && strpos($compiler_line, '-f') === false && (strpos($compiler_backup_line, '-f') !== false || strpos($compiler_backup_line, '-O'))) { $compiler_line .= ' ' . $compiler_backup_line; } $compiler_options = explode(' ', $compiler_line); foreach($compiler_options as $i => $option) { // Decide what to include and what not... D? if(!isset($option[2]) || $option[0] != '-' || $option[1] == 'L' || $option[1] == 'D' || $option[1] == 'I' || $option[1] == 'W' || isset($option[20])) { unset($compiler_options[$i]); } if(isset($option[1]) && $option[1] == 'l') { // If you're linking a library it's also useful for other purposes $library = substr($option, 1); // TODO XXX: scan the external dependencies to make sure $library is covered if not alert test profile maintainer... //unset($compiler_options[$i]); } } $compiler_options = implode(' ', array_unique($compiler_options)); //sort($compiler_options); // TODO: right now just keep overwriting $compiler to take the last compiler.. so TODO add support for multiple compiler reporting or decide what todo $compiler = array('compiler-type' => $compiler_type, 'compiler' => $compiler_choice, 'compiler-options' => $compiler_options); //echo PHP_EOL . 'DEBUG: ' . $compiler_type . ' ' . $compiler_choice . ' :: ' . $compiler_options . PHP_EOL; } } pts_file_io::delete($test_install_request->compiler_mask_dir, null, true); return $compiler; } protected static function install_test_process(&$test_install_request) { // Install a test $identifier = $test_install_request->test_profile->get_identifier(); $test_install_directory = $test_install_request->test_profile->get_install_dir(); pts_file_io::mkdir(dirname($test_install_directory)); pts_file_io::mkdir($test_install_directory); $installed = false; if(ceil(disk_free_space($test_install_directory) / 1048576) < ($test_install_request->test_profile->get_download_size() + 128)) { pts_client::$display->test_install_error('There is not enough space at ' . $test_install_directory . ' for the test files.'); } else if(ceil(disk_free_space($test_install_directory) / 1048576) < ($test_install_request->test_profile->get_environment_size(false) + 128)) { pts_client::$display->test_install_error('There is not enough space at ' . $test_install_directory . ' for this test.'); } else { pts_test_installer::setup_test_install_directory($test_install_request, true); // Download test files $download_test_files = pts_test_installer::download_test_files($test_install_request); if($download_test_files == false) { pts_client::$display->test_install_error('Downloading of needed test files failed.'); return false; } if($test_install_request->test_profile->get_file_installer() != false) { self::create_compiler_mask($test_install_request); pts_module_manager::module_process('__pre_test_install', $identifier); pts_client::$display->test_install_begin($test_install_request); $pre_install_message = $test_install_request->test_profile->get_pre_install_message(); $post_install_message = $test_install_request->test_profile->get_post_install_message(); $install_agreement = $test_install_request->test_profile->get_installation_agreement_message(); if(!empty($install_agreement)) { if(pts_strings::is_url($install_agreement)) { $install_agreement = pts_network::http_get_contents($install_agreement); if(empty($install_agreement)) { pts_client::$display->test_install_error('The user agreement could not be found. Test installation aborted.'); return false; } } echo $install_agreement . PHP_EOL; $user_agrees = pts_user_io::prompt_bool_input('Do you agree to these terms', false, 'INSTALL_AGREEMENT'); if(!$user_agrees) { pts_client::$display->test_install_error('User agreement failed; this test will not be installed.'); return false; } } pts_user_io::display_interrupt_message($pre_install_message); $install_time_length_start = microtime(true); $install_log = pts_tests::call_test_script($test_install_request->test_profile, 'install', null, $test_install_directory, $test_install_request->special_environment_vars, false); $test_install_request->install_time_duration = ceil(microtime(true) - $install_time_length_start); pts_user_io::display_interrupt_message($post_install_message); if(!empty($install_log)) { file_put_contents($test_install_directory . 'install.log', $install_log); pts_file_io::unlink($test_install_directory . 'install-failed.log'); pts_client::$display->test_install_output($install_log); } if(is_file($test_install_directory . 'install-exit-status')) { // If the installer writes its exit status to ~/install-exit-status, if it's non-zero the install failed $install_exit_status = pts_file_io::file_get_contents($test_install_directory . 'install-exit-status'); unlink($test_install_directory . 'install-exit-status'); if($install_exit_status != 0 && phodevi::is_windows() == false) { $install_error = null; // TODO: perhaps better way to handle this than to remove pts-install.xml pts_file_io::unlink($test_install_directory . 'pts-install.xml'); if(is_file($test_install_directory . 'install.log')) { $install_log = pts_file_io::file_get_contents($test_install_directory . 'install.log'); $install_error = pts_tests::scan_for_error($install_log, $test_install_directory); copy($test_install_directory . 'install.log', $test_install_directory . 'install-failed.log'); } pts_test_installer::setup_test_install_directory($test_install_request, true); // Remove installed files from the bunked installation pts_client::$display->test_install_error('The installer exited with a non-zero exit status.'); if($install_error != null) { $test_install_request->install_error = pts_tests::pretty_error_string($install_error); if($test_install_request->install_error != null) { pts_client::$display->test_install_error('ERROR: ' . $test_install_request->install_error); } } pts_client::$display->test_install_error('LOG: ' . str_replace(pts_client::user_home_directory(), '~/', $test_install_directory) . 'install-failed.log' . PHP_EOL); if(pts_client::do_anonymous_usage_reporting()) { // If anonymous usage reporting enabled, report test install failure to OpenBenchmarking.org pts_openbenchmarking_client::upload_usage_data('test_install_failure', array($test_install_request, $install_error)); } return false; } } pts_module_manager::module_process('__post_test_install', $identifier); $installed = true; if(pts_config::read_bool_config('PhoronixTestSuite/Options/Installation/RemoveDownloadFiles', 'FALSE')) { // Remove original downloaded files foreach($test_install_request->get_download_objects() as $download_object) { pts_file_io::unlink($test_install_directory . $download_object->get_filename()); } } } else { pts_client::$display->test_install_error('No installation script found.'); $installed = true; } // Additional validation checks? $custom_validated_output = pts_tests::call_test_script($test_install_request->test_profile, 'validate-install', PHP_EOL . 'Validating Installation...' . PHP_EOL, $test_install_directory, null, false); if(!empty($custom_validated_output) && !pts_strings::string_bool($custom_validated_output)) { $installed = false; } } echo PHP_EOL; return $installed; } public static function validate_md5_download_file($filename, $verified_md5) { $valid = false; if(is_file($filename)) { if(pts_flags::skip_md5_checks()) { $valid = true; } else if(!empty($verified_md5)) { $real_md5 = md5_file($filename); if(pts_strings::is_url($verified_md5)) { foreach(pts_strings::trim_explode("\n", pts_network::http_get_contents($verified_md5)) as $md5_line) { list($md5, $file) = explode(' ', $md5_line); if($md5_file == $filename) { if($md5 == $real_md5) { $valid = true; } break; } } } else if($real_md5 == $verified_md5) { $valid = true; } } else { $valid = true; } } return $valid; } public static function validate_sha256_download_file($filename, $verified_sha256) { $valid = false; if(is_file($filename)) { if(pts_flags::skip_md5_checks()) { $valid = true; } else if(!empty($verified_sha256)) { $real_sha256 = hash_file('sha256', $filename); if(pts_strings::is_url($verified_sha256)) { foreach(pts_strings::trim_explode("\n", pts_network::http_get_contents($verified_sha256)) as $sha256_line) { list($sha256, $file) = explode(' ', $sha256_line); if($sha256_file == $filename) { if($sha256 == $real_sha256) { $valid = true; } break; } } } else if($real_sha256 == $verified_sha256) { $valid = true; } } else { $valid = true; } } return $valid; } protected static function setup_test_install_directory(&$test_install_request, $remove_old_files = false) { $identifier = $test_install_request->test_profile->get_identifier(); pts_file_io::mkdir($test_install_request->test_profile->get_install_dir()); if($remove_old_files) { // Remove any (old) files that were installed $ignore_files = array('pts-install.xml', 'install-failed.log'); foreach($test_install_request->get_download_objects() as $download_object) { array_push($ignore_files, $download_object->get_filename()); } pts_file_io::delete($test_install_request->test_profile->get_install_dir(), $ignore_files); } pts_file_io::symlink(pts_client::user_home_directory() . '.Xauthority', $test_install_request->test_profile->get_install_dir() . '.Xauthority'); pts_file_io::symlink(pts_client::user_home_directory() . '.drirc', $test_install_request->test_profile->get_install_dir() . '.drirc'); } } ?> phoronix-test-suite/pts-core/objects/client/pts_test_execution.php0000644000175000017500000004447712171755437025756 0ustar michaelmichael. */ class pts_test_execution { public static function run_test(&$test_run_manager, &$test_run_request) { $test_identifier = $test_run_request->test_profile->get_identifier(); $extra_arguments = $test_run_request->get_arguments(); $arguments_description = $test_run_request->get_arguments_description(); // Do the actual test running process $test_directory = $test_run_request->test_profile->get_install_dir(); if(!is_dir($test_directory)) { return false; } $lock_file = $test_directory . 'run_lock'; if(pts_client::create_lock($lock_file) == false) { pts_client::$display->test_run_error('The ' . $test_identifier . ' test is already running.'); return false; } $test_run_request->test_result_buffer = new pts_test_result_buffer(); $execute_binary = $test_run_request->test_profile->get_test_executable(); $times_to_run = $test_run_request->test_profile->get_times_to_run(); $ignore_runs = $test_run_request->test_profile->get_runs_to_ignore(); $test_type = $test_run_request->test_profile->get_test_hardware_type(); $allow_cache_share = $test_run_request->test_profile->allow_cache_share(); $min_length = $test_run_request->test_profile->get_min_length(); $max_length = $test_run_request->test_profile->get_max_length(); if($test_run_request->test_profile->get_environment_testing_size() > 1 && ceil(disk_free_space($test_directory) / 1048576) < $test_run_request->test_profile->get_environment_testing_size()) { // Ensure enough space is available on disk during testing process pts_client::$display->test_run_error('There is not enough space (at ' . $test_directory . ') for this test to run.'); pts_client::release_lock($lock_file); return false; } $to_execute = $test_run_request->test_profile->get_test_executable_dir(); $pts_test_arguments = trim($test_run_request->test_profile->get_default_arguments() . ' ' . str_replace($test_run_request->test_profile->get_default_arguments(), '', $extra_arguments) . ' ' . $test_run_request->test_profile->get_default_post_arguments()); $extra_runtime_variables = pts_tests::extra_environmental_variables($test_run_request->test_profile); // Start $cache_share_pt2so = $test_directory . 'cache-share-' . PTS_INIT_TIME . '.pt2so'; $cache_share_present = $allow_cache_share && is_file($cache_share_pt2so); $test_run_request->set_used_arguments_description($arguments_description); pts_module_manager::module_process('__pre_test_run', $test_run_request); $time_test_start = time(); pts_client::$display->test_run_start($test_run_manager, $test_run_request); if(!$cache_share_present) { pts_tests::call_test_script($test_run_request->test_profile, 'pre', 'Running Pre-Test Script', $test_directory, $extra_runtime_variables, true); } pts_user_io::display_interrupt_message($test_run_request->test_profile->get_pre_run_message()); $runtime_identifier = time(); $execute_binary_prepend = ''; if(!$cache_share_present && $test_run_request->test_profile->is_root_required()) { $execute_binary_prepend = PTS_CORE_STATIC_PATH . 'scripts/root-access.sh '; } if($allow_cache_share && !is_file($cache_share_pt2so)) { $cache_share = new pts_storage_object(false, false); } if($test_run_manager->get_results_identifier() != null && $test_run_manager->get_file_name() != null && pts_config::read_bool_config('PhoronixTestSuite/Options/Testing/SaveTestLogs', 'FALSE')) { $backup_test_log_dir = PTS_SAVE_RESULTS_PATH . $test_run_manager->get_file_name() . '/test-logs/active/' . $test_run_manager->get_results_identifier() . '/'; pts_file_io::delete($backup_test_log_dir); pts_file_io::mkdir($backup_test_log_dir, 0777, true); } else { $backup_test_log_dir = false; } for($i = 0, $abort_testing = false, $time_test_start_actual = time(), $defined_times_to_run = $times_to_run; $i < $times_to_run && $i < 256 && !$abort_testing; $i++) { pts_client::$display->test_run_instance_header($test_run_request); $test_log_file = $test_directory . basename($test_identifier) . '-' . $runtime_identifier . '-' . ($i + 1) . '.log'; $is_expected_last_run = ($i == ($times_to_run - 1)); $test_extra_runtime_variables = array_merge($extra_runtime_variables, array( 'LOG_FILE' => $test_log_file )); $restored_from_cache = false; if($cache_share_present) { $cache_share = pts_storage_object::recover_from_file($cache_share_pt2so); if($cache_share) { $test_result = $cache_share->read_object('test_results_output_' . $i); $test_extra_runtime_variables['LOG_FILE'] = $cache_share->read_object('log_file_location_' . $i); if($test_extra_runtime_variables['LOG_FILE'] != null) { file_put_contents($test_extra_runtime_variables['LOG_FILE'], $cache_share->read_object('log_file_' . $i)); $test_run_time = 0; // This wouldn't be used for a cache share since it would always be the same, but declare the value so the variable is at least initialized $restored_from_cache = true; } } unset($cache_share); } if($restored_from_cache == false) { $test_run_command = 'cd ' . $to_execute . ' && ' . $execute_binary_prepend . './' . $execute_binary . ' ' . $pts_test_arguments . ' 2>&1'; pts_client::test_profile_debug_message('Test Run Command: ' . $test_run_command); $is_monitoring = pts_test_result_parser::system_monitor_task_check($test_run_request->test_profile); $test_run_time_start = time(); if(phodevi::is_windows() || pts_client::read_env('USE_PHOROSCRIPT_INTERPRETER') != false) { $phoroscript = new pts_phoroscript_interpreter($to_execute . '/' . $execute_binary, $test_extra_runtime_variables, $to_execute); $phoroscript->execute_script($pts_test_arguments); $test_result = null; } else { $test_result = pts_client::shell_exec($test_run_command, $test_extra_runtime_variables); } $test_run_time = time() - $test_run_time_start; $monitor_result = $is_monitoring ? pts_test_result_parser::system_monitor_task_post_test($test_run_request->test_profile) : 0; } if(!isset($test_result[10240]) || (pts_c::$test_flags & pts_c::debug_mode)) { pts_client::$display->test_run_instance_output($test_result); } if(is_file($test_log_file) && trim($test_result) == null && (filesize($test_log_file) < 10240 || (pts_c::$test_flags & pts_c::debug_mode))) { $test_log_file_contents = file_get_contents($test_log_file); pts_client::$display->test_run_instance_output($test_log_file_contents); unset($test_log_file_contents); } $exit_status_pass = true; if(is_file($test_directory . 'test-exit-status')) { // If the test script writes its exit status to ~/test-exit-status, if it's non-zero the test run failed $exit_status = pts_file_io::file_get_contents($test_directory . 'test-exit-status'); unlink($test_directory . 'test-exit-status'); if($exit_status != 0) { pts_client::$display->test_run_instance_error('The test exited with a non-zero exit status.'); if($is_expected_last_run && is_file($test_log_file)) { $scan_log = pts_file_io::file_get_contents($test_log_file); $test_run_error = pts_tests::scan_for_error($scan_log, $test_run_request->test_profile->get_test_executable_dir()); if($test_run_error) { pts_client::$display->test_run_instance_error('E: ' . $test_run_error); } } $exit_status_pass = false; } } if(!in_array(($i + 1), $ignore_runs) && $exit_status_pass) { if(isset($monitor_result) && $monitor_result != 0) { $test_run_request->active_result = $monitor_result; } else { pts_test_result_parser::parse_result($test_run_request, $test_extra_runtime_variables['LOG_FILE']); } pts_client::test_profile_debug_message('Test Result Value: ' . $test_run_request->active_result); if(!empty($test_run_request->active_result)) { if($test_run_time < 3 && intval($test_run_request->active_result) == $test_run_request->active_result && $test_run_request->test_profile->get_estimated_run_time() > 60) { // If the test ended in less than 3 seconds, outputted some int, and normally the test takes much longer, then it's likely some invalid run pts_client::$display->test_run_instance_error('The test run ended prematurely.'); if($is_expected_last_run && is_file($test_log_file)) { $scan_log = pts_file_io::file_get_contents($test_log_file); $test_run_error = pts_tests::scan_for_error($scan_log, $test_run_request->test_profile->get_test_executable_dir()); if($test_run_error) { pts_client::$display->test_run_instance_error('E: ' . $test_run_error); } } } else { $test_run_request->test_result_buffer->add_test_result(null, $test_run_request->active_result, null, null, $test_run_request->active_min_result, $test_run_request->active_max_result); } } else if($test_run_request->test_profile->get_display_format() != 'NO_RESULT') { pts_client::$display->test_run_instance_error('The test run did not produce a result.'); if($is_expected_last_run && is_file($test_log_file)) { $scan_log = pts_file_io::file_get_contents($test_log_file); $test_run_error = pts_tests::scan_for_error($scan_log, $test_run_request->test_profile->get_test_executable_dir()); if($test_run_error) { pts_client::$display->test_run_instance_error('E: ' . $test_run_error); } } } if($allow_cache_share && !is_file($cache_share_pt2so)) { $cache_share->add_object('test_results_output_' . $i, $test_run_request->active_result); $cache_share->add_object('log_file_location_' . $i, $test_extra_runtime_variables['LOG_FILE']); $cache_share->add_object('log_file_' . $i, (is_file($test_log_file) ? file_get_contents($test_log_file) : null)); } } if($is_expected_last_run && $test_run_request->test_result_buffer->get_count() > floor(($i - 2) / 2)) { // The later check above ensures if the test is failing often the run count won't uselessly be increasing // Should we increase the run count? $increase_run_count = false; if($defined_times_to_run == ($i + 1) && $test_run_request->test_result_buffer->get_count() > 0 && $test_run_request->test_result_buffer->get_count() < $defined_times_to_run && $i < 64) { // At least one run passed, but at least one run failed to produce a result. Increase count to try to get more successful runs $increase_run_count = $defined_times_to_run - $test_run_request->test_result_buffer->get_count(); } else if($test_run_request->test_result_buffer->get_count() >= 2 && $test_run_manager->do_dynamic_run_count()) { // Dynamically increase run count if needed for statistical significance or other reasons $increase_run_count = $test_run_manager->increase_run_count_check($test_run_request, $defined_times_to_run, $test_run_time); if($increase_run_count === -1) { $abort_testing = true; } else if($increase_run_count == true) { // Just increase the run count one at a time $increase_run_count = 1; } } if($increase_run_count > 0) { $times_to_run += $increase_run_count; $is_expected_last_run = false; //$test_run_request->test_profile->set_times_to_run($times_to_run); } } if($times_to_run > 1 && $i < ($times_to_run - 1)) { if($cache_share_present == false) { pts_tests::call_test_script($test_run_request->test_profile, 'interim', 'Running Interim Test Script', $test_directory, $extra_runtime_variables, true); sleep(2); // Rest for a moment between tests } pts_module_manager::module_process('__interim_test_run', $test_run_request); } if(is_file($test_log_file)) { if($is_expected_last_run) { // For now just passing the last test log file... // TODO XXX: clean this up with log files to preserve when needed, let multiple log files exist for extra_data, etc pts_test_result_parser::generate_extra_data($test_run_request, $test_log_file); } if($backup_test_log_dir) { copy($test_log_file, $backup_test_log_dir . basename($test_log_file)); } if(pts_client::test_profile_debug_message('Log File At: ' . $test_log_file) == false) { unlink($test_log_file); } } if(is_file(PTS_USER_PATH . 'halt-testing') || is_file(PTS_USER_PATH . 'skip-test')) { pts_client::release_lock($lock_file); return false; } pts_client::$display->test_run_instance_complete($test_run_request); } $time_test_end_actual = time(); if($cache_share_present == false) { pts_tests::call_test_script($test_run_request->test_profile, 'post', 'Running Post-Test Script', $test_directory, $extra_runtime_variables, true); } if($abort_testing) { pts_client::$display->test_run_error('This test execution has been abandoned.'); return false; } // End $time_test_end = time(); $time_test_elapsed = $time_test_end - $time_test_start; $time_test_elapsed_actual = $time_test_end_actual - $time_test_start_actual; if(!empty($min_length)) { if($min_length > $time_test_elapsed_actual) { // The test ended too quickly, results are not valid pts_client::$display->test_run_error('This test ended prematurely.'); return false; } } if(!empty($max_length)) { if($max_length < $time_test_elapsed_actual) { // The test took too much time, results are not valid pts_client::$display->test_run_error('This test run was exhausted.'); return false; } } if($allow_cache_share && !is_file($cache_share_pt2so) && $cache_share instanceof pts_storage_object) { $cache_share->save_to_file($cache_share_pt2so); unset($cache_share); } if($test_run_manager->get_results_identifier() != null && (pts_config::read_bool_config('PhoronixTestSuite/Options/Testing/SaveInstallationLogs', 'FALSE'))) { if(is_file($test_run_request->test_profile->get_install_dir() . 'install.log')) { $backup_log_dir = PTS_SAVE_RESULTS_PATH . $test_run_manager->get_file_name() . '/installation-logs/' . $test_run_manager->get_results_identifier() . '/'; pts_file_io::mkdir($backup_log_dir, 0777, true); copy($test_run_request->test_profile->get_install_dir() . 'install.log', $backup_log_dir . basename($test_identifier) . '.log'); } } // Fill in missing test details if(empty($arguments_description)) { $arguments_description = $test_run_request->test_profile->get_test_subtitle(); } $file_var_checks = array( array('pts-results-scale', 'set_result_scale', null), array('pts-results-proportion', 'set_result_proportion', null), array('pts-results-quantifier', 'set_result_quantifier', null), array('pts-test-version', 'set_version', null), array('pts-test-description', null, 'set_used_arguments_description') ); foreach($file_var_checks as &$file_check) { list($file, $set_function, $result_set_function) = $file_check; if(is_file($test_directory . $file)) { $file_contents = pts_file_io::file_get_contents($test_directory . $file); unlink($test_directory . $file); if(!empty($file_contents)) { if($set_function != null) { call_user_func(array($test_run_request->test_profile, $set_function), $file_contents); } else if($result_set_function != null) { call_user_func(array($test_run_request, $result_set_function), $file_contents); } } } } if(empty($arguments_description)) { $arguments_description = 'Phoronix Test Suite v' . PTS_VERSION; } foreach(pts_client::environmental_variables() as $key => $value) { $arguments_description = str_replace('$' . $key, $value, $arguments_description); if(!in_array($key, array('VIDEO_MEMORY', 'NUM_CPU_CORES', 'NUM_CPU_JOBS'))) { $extra_arguments = str_replace('$' . $key, $value, $extra_arguments); } } // Any device notes to add to PTS test notes area? foreach(phodevi::read_device_notes($test_type) as $note) { pts_test_notes_manager::add_note($note); } // As of PTS 4.4, this is removed and superceded effectively by reporting the notes to table // Any special information (such as forced AA/AF levels for graphics) to add to the description string of the result? /* if(($special_string = phodevi::read_special_settings_string($test_type)) != null) { if(strpos($arguments_description, $special_string) === false) { if($arguments_description != null) { $arguments_description .= ' | '; } $arguments_description .= $special_string; } } */ // Result Calculation $test_run_request->set_used_arguments_description($arguments_description); $test_run_request->set_used_arguments($extra_arguments); pts_test_result_parser::calculate_end_result($test_run_request); // Process results pts_client::$display->test_run_end($test_run_request); pts_user_io::display_interrupt_message($test_run_request->test_profile->get_post_run_message()); pts_module_manager::module_process('__post_test_run', $test_run_request); $report_elapsed_time = $cache_share_present == false && $test_run_request->get_result() != 0; pts_tests::update_test_install_xml($test_run_request->test_profile, ($report_elapsed_time ? $time_test_elapsed : 0)); pts_storage_object::add_in_file(PTS_CORE_STORAGE, 'total_testing_time', ($time_test_elapsed / 60)); if($report_elapsed_time && pts_client::do_anonymous_usage_reporting() && $time_test_elapsed >= 60) { // If anonymous usage reporting enabled, report test run-time to OpenBenchmarking.org pts_openbenchmarking_client::upload_usage_data('test_complete', array($test_run_request, $time_test_elapsed)); } // Remove lock pts_client::release_lock($lock_file); } } ?> phoronix-test-suite/pts-core/objects/client/pts_module.php0000644000175000017500000002114512174025360024150 0ustar michaelmichael. */ class pts_module { const MODULE_UNLOAD = "MODULE_UNLOAD"; const QUIT_PTS_CLIENT = "QUIT_PTS_CLIENT"; public static function save_dir() { $prefix_dir = PTS_MODULE_DATA_PATH; pts_file_io::mkdir($prefix_dir); return $prefix_dir . str_replace('_', '-', self::module_name()) . '/'; } public static function is_module($name) { return is_file(PTS_MODULE_LOCAL_PATH . $name . ".php") || is_file(PTS_MODULE_PATH . $name . ".php"); } public static function module_config_save($module_name, $set_options = null) { // Validate the config files, update them (or write them) if needed, and other configuration file tasks pts_file_io::mkdir(PTS_MODULE_DATA_PATH . $module_name); $settings_to_write = array(); if(is_file(PTS_MODULE_DATA_PATH . $module_name . "/module-settings.xml")) { $module_config_parser = new nye_XmlReader(PTS_MODULE_DATA_PATH . $module_name . "/module-settings.xml"); $option_identifier = $module_config_parser->getXMLArrayValues('PhoronixTestSuite/ModuleSettings/Option/Identifier'); $option_value = $module_config_parser->getXMLArrayValues('PhoronixTestSuite/ModuleSettings/Option/Value'); for($i = 0; $i < count($option_identifier); $i++) { $settings_to_write[$option_identifier[$i]] = $option_value[$i]; } } foreach($set_options as $identifier => $value) { $settings_to_write[$identifier] = $value; } $config = new nye_XmlWriter(); foreach($settings_to_write as $identifier => $value) { $config->addXmlNode('PhoronixTestSuite/ModuleSettings/Option/Identifier', $identifier); $config->addXmlNode('PhoronixTestSuite/ModuleSettings/Option/Value', $value); } $config->saveXMLFile(PTS_MODULE_DATA_PATH . $module_name . "/module-settings.xml"); } public static function is_module_setup() { $module_name = self::module_name(); $is_setup = true; $module_setup_options = pts_module_manager::module_call($module_name, "module_setup"); foreach($module_setup_options as $option) { if($option instanceOf pts_module_option) { if(pts_module::read_option($option->get_identifier()) == false && $option->setup_check_needed()) { $is_setup = false; break; } } } return $is_setup; } public static function read_variable($var) { // For now this is just readung from the real env return trim(getenv($var)); } public static function valid_run_command($module, $command = null) { if($command == null) { if(strpos($module, '.') != false) { list($module, $command) = explode('.', $module); } else { $command = 'run'; } } if(!pts_module_manager::is_module_attached($module)) { pts_module_manager::attach_module($module); } $all_options = pts_module_manager::module_call($module, 'user_commands'); $valid = count($all_options) > 0 && ((isset($all_options[$command]) && method_exists($module, $all_options[$command])) || in_array($command, array('help'))); return $valid ? array($module, $command) : false; } public static function read_option($identifier, $default_fallback = false) { $module_name = self::module_name(); $value = false; $module_config_parser = new nye_XmlReader(PTS_MODULE_DATA_PATH . $module_name . "/module-settings.xml"); $option_identifier = $module_config_parser->getXMLArrayValues('PhoronixTestSuite/ModuleSettings/Option/Identifier'); $option_value = $module_config_parser->getXMLArrayValues('PhoronixTestSuite/ModuleSettings/Option/Value'); for($i = 0; $i < count($option_identifier) && $value == false; $i++) { if($option_identifier[$i] == $identifier) { $value = $option_value[$i]; } } if($default_fallback && empty($value)) { // Find the default value $module_options = call_user_func(array($module_name, "module_setup")); for($i = 0; $i < count($module_options) && $value == false; $i++) { if($module_options[$i]->get_identifier() == $identifier) { $value = $module_options[$i]->get_default_value(); } } } return $value; } public static function read_all_options() { $module_name = self::module_name(); $options = array(); $module_config_parser = new nye_XmlReader(PTS_MODULE_DATA_PATH . $module_name . "/module-settings.xml"); $option_identifier = $module_config_parser->getXMLArrayValues('PhoronixTestSuite/ModuleSettings/Option/Identifier'); $option_value = $module_config_parser->getXMLArrayValues('PhoronixTestSuite/ModuleSettings/Option/Value'); for($i = 0; $i < count($option_identifier); $i++) { $options[$option_identifier[$i]] = $option_value[$i]; } return $options; } public static function set_option($identifier, $value) { pts_module::module_config_save(self::module_name(), array($identifier => $value)); } public static function save_file($file, $contents = null, $append = false) { // Saves a file for a module $save_base_dir = self::save_dir(); pts_file_io::mkdir($save_base_dir); if(($extra_dir = dirname($file)) != "." && !is_dir($save_base_dir . $extra_dir)) { mkdir($save_base_dir . $extra_dir); } if($append) { if(is_file($save_base_dir . $file)) { if(file_put_contents($save_base_dir . $file, $contents . "\n", FILE_APPEND) != false) { return $save_base_dir . $file; } } } else { if(file_put_contents($save_base_dir . $file, $contents) != false) { return $save_base_dir . $file; } } return false; } public static function read_file($file) { $file = self::save_dir() . $file; return is_file($file) ? file_get_contents($file) : false; } public static function is_file($file) { $file = self::save_dir() . $file; return is_file($file); } public static function remove_file($file) { $file = self::save_dir() . $file; return is_file($file) && unlink($file); } public static function copy_file($from_file, $to_file) { // Copy a file for a module $save_base_dir = self::save_dir(); pts_file_io::mkdir($save_base_dir); if(($extra_dir = dirname($to_file)) != "." && !is_dir($save_base_dir . $extra_dir)) { mkdir($save_base_dir . $extra_dir); } if(is_file($from_file) && (!is_file($save_base_dir . $to_file) || md5_file($from_file) != md5_file($save_base_dir . $to_file))) { if(copy($from_file, $save_base_dir . $to_file)) { return $save_base_dir . $to_file; } } return false; } public static function pts_fork_function($function) { self::pts_timed_function($function, -1); } public static function pts_timed_function($function, $time) { if(($time < 0.5 && $time != -1) || $time > 300) { return; } if(function_exists('pcntl_fork')) { $pid = pcntl_fork(); if($pid != -1) { if($pid) { return $pid; } else { $loop_continue = true; /* ML: I think this below check can be safely removed $start_id = pts_unique_runtime_identifier(); && ($start_id == pts_unique_runtime_identifier() || $start_id == PTS_INIT_TIME) */ while(pts_test_run_manager::test_run_process_active() !== -1 && is_file(PTS_USER_LOCK) && $loop_continue) { call_user_func(array(self::module_name(), $function)); if($time > 0) { sleep($time); } else if($time == -1) { $loop_continue = false; } } exit(0); } } } else { pts_client::$display->generic_error("php-pcntl must be installed for the " . self::module_name() . " module."); } } private static function module_name() { $module_name = "unknown"; if(($current = pts_module_manager::get_current_module()) != null) { $module_name = $current; } else { $bt = debug_backtrace(); for($i = 0; $i < count($bt) && $module_name == "unknown"; $i++) { if($bt[$i]["class"] != "pts_module") { $module_name = $bt[$i]["class"]; } } } return $module_name; } } ?> phoronix-test-suite/pts-core/results-viewer/pts-results-viewer.xsl0000664000175000017500000001272212165661730025723 0ustar michaelmichael <xsl:value-of select="PhoronixTestSuite/Generated/Title" /> - <xsl:value-of select="PhoronixTestSuite/Generated/TestClient" /> - Results

Generated by on .

System Information

autoautoresult-graphs/systems.svg
autoautoresult-graphs/detailed_component.svg

Results Overview

autoautoresult-graphs/radar.svg
autoautoresult-graphs/overview.svg
autoautoresult-graphs/visualize.svg

Test Results

autoautoresult-graphs/.svg
phoronix-test-suite/pts-core/results-viewer/phoronix-test-suite.css0000644000175000017500000000702312023467622026044 0ustar michaelmichaelbody { margin: 0; padding: 0; font: 13px "Liberation Sans", "Bitstream Vera Sans", sans-serif; background: #BABABA url(background-pattern.png) repeat; color: #000; } a { color: inherit; text-decoration: none; } a:hover { text-decoration: underline; } div#pts_container { text-align: left; min-width: 940px; background: #FFF; width: auto; margin: 60px; overflow: hidden; border: 1px solid #D7D7D7; box-shadow: 1px 1px 4px #000; -moz-box-shadow: 1px 1px 4px #000; -webkit-box-shadow: 1px 1px 4px #000; } div.pts_column_head { font-size: 13px; color: #FFF; background-color: #454545; font-weight: bold; display: table-row; } a#pts_top_logo { display: block; width: 160px; height: 83px; background: transparent url(pts-logo-top.png); opacity: 0.48; filter: alpha(opacity=48); } a#pts_top_logo:hover { opacity: 1.0; filter: alpha(opacity=100); } h1 { margin-left: 10px; margin-top: 10px; font-size: 21px; color: #044374; font-weight: bold; } p { margin-left: 10px; } table { text-align: center; background-color: #F8F8F8; margin: 6px 10px; border-collapse: collapse; } td { border: solid #949494 1px; vertical-align: top; padding: 2px 2px 6px } tr.pts_column_head td { font-size: 13px; color: #FFF; background-color: #454545; font-weight: bold; padding: 0 2px; } div.pts_table_box_out { width: 100%; overflow: auto; } div.pts_chart_box { width: 95%; overflow: hidden; margin: 5px auto; } div.pts_chart_box a { text-decoration: none; font-weight: bold; } div.pts_chart_box a:hover { text-decoration: underline; } div#pts_benchmark_area { background-color: #FFF; margin: 10px auto; color: #000; overflow: hidden; } div.pts_benchmark_bar { overflow: hidden; background-color: #454545; color: #FFF; padding: 4px; border: solid #6B6B6B 1px; margin: 0 10px; clear: both; } span.pts_benchmark_bar_header { font-size: 18px; font-weight: bold; } span.pts_benchmark_bar_version { vertical-align: super; padding-left: 5px; font-size: 10px; } div.pts_benchmark_text { padding: 30px 15px 15px; float: left; overflow: hidden; color: #333; } div.pts_benchmark_img_area { padding: 20px 10px; float: left; overflow: hidden; height: 100%; text-align: center; } div.pts_benchmark_img_table_area { padding: 20px 10px; float: right; overflow: auto; height: 100%; text-align: center; } div#pts_banner_nav { height: 28px; background: #266c29 url(horizontal-nav-bg.png) repeat-x; border: solid #949494 1px; text-align: center; text-shadow: #000 0.1em 0.1em 0.2em; color: #FFF; font-weight: bold; font-size: 14px; padding-right: 1px; margin: 4px 10px; } div#pts_banner_nav a { width: 15%; height: 100%; display: block; float: left; line-height: 28px; margin-right: -1px; border: solid #333; border-width: 0 1px 0 0; } div#pts_banner_nav a:hover { text-decoration: none; background: #266c29 url(horizontal-nav-bg-hover.png) repeat-x; } div#pts_footer { clear: both; top: 20px; width: 100%; border: 0 solid #D4D4D4; border-width: 1px 0 0; padding: 15px 0 10px; color: #757575; font-size: 10px; } div#pts_footer a { text-decoration: none; } div#pts_footer a:hover, div#oborg_main_area blockquote a { text-decoration: underline; } div#pts_footer p { margin: 1px; text-indent: 20px; } div#pts_footer_logo { float: right; width: 96px; height: 50px; margin: 0 5px 10px; } div#pts_footer_logo a { display: block; width: 100%; height: 100%; background: transparent url(pts-logo-bottom.png); opacity: 0.48; filter: alpha(opacity=48); } div#pts_footer_logo a:hover { opacity: 1.0; filter: alpha(opacity=100); } phoronix-test-suite/pts-core/results-viewer/pts-logo-top.png0000644000175000017500000001012212000141724024407 0ustar michaelmichael‰PNG  IHDR SÉ šsBIT|dˆ pHYsJJŽØ°*tEXtSoftwarewww.inkscape.org›î<ÏIDATxœíy´]E•‡¿ßN3a†È”0Ó!Œ*$ "ƒ@·`7Y¨i—ŠèZ ¡ZQ™”,Ú(h‘A ƒ4`„Q L!„Lj÷U79ܼ÷nÝù¾p¾µÎZïœSÃ>u÷;Uµk×>rw3’F¿¬‘l¡»í€8%u2´Û´€•€Ýj¤YÐ AJêǺ-@É›RKºJ©€%]ey–4Á„ !Lª•î²Ë.[³õ— øÇ݇ûUÙ—t•RKºJ©€%]¥TÀ’®R*`IW)°¤«” XÒUJ,é*¥–t•RKºJ©€%]¥åkÁ’ÖÖÖÞæ¯»ûÛ­®k0!i0ø±}Ô¡ªºûŪ«nšR@I+ã€}€Û·¯´³€Ç)ÀÀ=>Ø÷Ô@ÒVÀ1ÀáÀ]ã-`ùR@I#ãñÀz™Ù6HÇß§ÏJšüÈÝg7"G¯"éCÄgü<0¤»Òô6u%­'éûÀ àò•¯/6NfJ:IÒ*M”Õ3HÚx ˜@©|5ÉR@IÃ$Ì$¾ù†µP†5³€§$ý[ Ëí8IþßÐÏ0¤dYj* ¤ ß§«µQ–À%’®–´rëi ’.¢|ëÕÅ€ (igà`ΈÀ?SÒ8jP é#Àµ”f­ºé·Á$ÜlÜ9q–0xPÒv]¨»þ‹hv*©“>PÒNÀ5@7»ÂÀÍ’6è¢ 5‘´'ðÝ–c°²Œ&ùnš™•:ð:°q’Ñ(#%u÷…M”3DÒØ&òyÂÝgÎÿ½Ž¼‹ˆ3ä™Ä6êó:TOC¼O%­üŠú»ÝùÄÙßõÀÝÀËîþ·TæÊÀ&À¾DƒìÞÕõÖ`7à àÈ:e*2 ø]ù‹ ü @’ŸÌÌw9p‚»¿Õ"9– ªáxjÇY)2¸8§¿†u÷D»á àBI›gÔŸ#Æx„¤«ÝýÆ:dë;’g ý©»Oh·0íF’F=²Vº!C†¼úàƒÎÏ)s‰JZ8¹yî>ëî/Õ‘wø¢¤ó‰Q­¶ÌÌz–¤Éîþ^=õµ™M3Ò̾ÑnA:ÁرcWœ;wî3I#ö¤5)NB¾MþåK}êU¾"î> ظ33˶Äș Mý ;b „Á;Öq™y®p÷c+c¼fHkÀ÷efùÏ4NíVÍHójÛ¥ÄTÞ€_$ÎXkñ'àØV f·‡Ïe$ߘøzïr”k‡¶K1ˆ1IŽÊH»8ÚݵZˆdÖøRfò/´ºþ&˜U; ›KÚ«í’ R Øž¼Áô¥î>½]‚¸û-DN-ÆIêZ0*#Ïžw±¤f<‡–[†ýój€3Ú, À™D{â@ !:ÁfͲN4µ‚% wŸ%é!`çy¶—t*ðGâp£†è0Ø'8C©Ýxr÷WÚ- ÑSúu`Ýév§>\èî[7,ÕÀÜD^®\ØêÊ%-^ž$¶É U+5=£2ÒMn· Úï¶j·,upðFë_ø0°QÁ_’ôsI¹öÕ®bäÿk· ÎHSÓß)’)é´nËQÀ€¦I:WROû'ynD œ §®v:Æ6Â…Ào»-DCˆ+0·¦Š=‰‘÷c¾ÜnA äØÖŠnb!#}[C»{ :Ò>ÛÎzdà{ÕËÜÈÛŸÚôªGä˜XŠ¶ÈœEïÚmºq÷7‰?ÓÚYOƒì \•l¾=E/ºç¸â•.×߭펭îþ4qûB=3ôNq8qlØSô¢æÌÊ— Ü}>ÑtS‹ŽÌœÝýmw?Œ8+}´uÖÁé)˜@ÏЋŸi88#Í_ªÎ§SÛvx Ñf×Üý6I£‰6ƒˆÝóÆÄ7ñJ’£ŠŸ®ìDecÆŒ™(iÀgí)LñS¶ÏH:µêüÿˆ¡Aâ Iêd8T׃é8­r=yô´b<6„èOù ¢“oÎl÷:¤€ÀDwpìÝk]p®KØíUçS2òlDœ©vw_äî [pÌs÷‡Ýý¢¿äSÕï'©gvðõŒJÚ˜<˜Ç’Wu‘;w3ò~GR+£:ô iù혌¤ÃˆÊÚôŒ÷ÖæŒ.¯¾V#r– 7¾U—Tƒw¿›<[dÏlúï ”tyÝãú¿\”YÝ)’r&:ƒ•;äúm—"“®+ ¤Ã€ïe&¿ÀÝ_ë놻ßÜ–S%p¥¤½3ëll’‘fNۥȤ« (éDà:ò¶gÎή‘æ›ä-Í nOoÞå†E"Çí¬“kûÒ”´µ¤ÉD…Ê•áìZ›ºÝ}*ðóÌò†çKºKR-Î`áÇäííÉ™-w„Ž)`Š1¸¤ŸÝ»¬#ûtà‡™i'õ8Ï~¸[Òm’ŽKç’FHºž¼5¹û_Û-S.¹†è¯Jj$ÆÈpâŒkcbÄ…œmŒÕÌ>",ÔÄÝ_’ôiàÔ·â°o:.”ô2qÃÑ, :&Íܽß0’~AkxDÅ=Šü—É í§~rð?Ú*Eÿbô…º6C¹ûý’Ž!Føj„éè‹Z?à!D/å^d>0©ÛBéú,¸ßt÷Z›”úÄݯe9¶ù5È»{'};kÒ« ¸8ÎÝÏk¦w?“¸8g•dyç)¢±¿§èE|دUWq÷ID¯à>í‡æ÷âÎ^SÀ‡€]ä7BZ¢Ú…ü@HËs€Ãܽڅ­'èü+q!}wŸÙŽ Üý9w߇hþùs;êèA¦»µúº•t[ß&†…ÛÒÝ/O›{ÚJ ²#qlØ“o…0ŸÉbL;é´‚n8¤¾F´Ñ]ü:×¾×J’¢O&IÚ…¸_b/btþÁì®õ1¾÷%ÍÄnì$¹ xËdkáÄÙç|â:î `š»·*FKKp÷ˆßB!mâIŒ4°6°:Ë*d­X†_¦sÿØ8i›Ìl·Ò½øâ‹>|øðœ0zYáy!z†ä¸¨¯ßŸJII3t{ Xò§TÀ’®R*`IW)°¤«” XÒUê2˜ÙP–F pàõÂ{Ui~ <B8µ5"¶3[X-„ÐpDÑTÆê5’½Bx³Ñ:Á̆7ùž¦‡ê²¹šÙÚ@!´íóbõ¾·'Æey™èu¼ÀÌf˜Ù¿ÒlC^ÐË^àÀóM–q=„Íl3;ÄÌ>šºŒâ½5Ìlw3[ÍÌV1³ƒÌlõÂýaf¶g*­>ÊÞÁÌ6Oobfôñx‹ÂrÌl;3ÓGYÛ™YŸQ»B‹BoUâꯅÞ)”ef6ÆÌŽ0³úi—-Ìì3fö±ŠÌf¶)1âÖ¸Ô.»ö•71¸/„03Éø^áÖÂâTÖª©Œ%!:R{îžºÝ /“†šÙºÄ/*ì ìžÒ®\È¿‚™íef‡§7p6žq¬çîH-É%éî¤k_J×þ!ÿEÒå’~ éo’æJzSÒ…Õì3ôEæŒ&NXÖÖ!>×X3«©_*à#ÀùD/ãmCÕ.3*ãÄ’Óf¶&QÑþP•§r^=¶©ÞÃúQà•Â?·»À½}äB(Æ·®9Of¥ñÄ™üç£CõzõÅDÏš³Y:;¾$Ý«|¡þ7éþÀ³f–³Ï·OBB8“ óU`²™µã›u•1ó5,}®Sˆäk†EnTo !\B˜VmÌ`.1®su„¦Êy-¯›W€µŠàBþVyì|•Ø8Óo•ÙBPÕq,™,œlGŒx™}¥™JC&° ¼q½Ñ€™•çڵ窹¯ã+!Iaï'n*Rùf]-»{‰ûn—„Ó0³Ęw¹ßî3ÛŸèÓw0Ñ q¶™}¼Ùr‰Ã•§#k% !L!Œ'ö n-†W[ 2Ä^¨âzW™•¯qf|7£œŠ!»8Ë}€¸ïäˆ:eº¢÷dà3›LŒg2ŽõœB-Ãðdâæ¢Ifv±{™ÌÎmF(3Ûøpbaª™=BTôÿ1³šY1 !¸™üÊÌ~Jì²æCƒ\Bx.½íF·mw»?àXá&b€‰fvK¡Ï¯J™ÙDÏè)DÇÚ¯¥[?I²L7³iÀ×’ ëpòÞ€·“O4³‹‰+^sÌì$àÇf¶¸™¨èã€ó«æËÊJüæF­£Â;ÄÿÊ>&s?ËJa#Pá>âfQw"ÆP>©ç­T×û¶¦ñÞaÄIÂxâ@û^`ÿBQ®€'ªäx„÷vìYÞÞwQ~˜êòTÇ£ä¨{:pO_7B7]ÿ7$n ¸ø;–î[~šh@¾ø:QùÎ*俟숔¦?ž$*݃ÄvZBx¼êYß¾’äý±½‹Ã˜‡)´Wámâæ±QÀU¤7aá"âGÇÇÿ±¾GœXÕœ@ý?+K»^™ŽIEND®B`‚phoronix-test-suite/pts-core/results-viewer/pts-logo-bottom.png0000644000175000017500000000457712000142264025132 0ustar michaelmichael‰PNG  IHDR`2£ÞÞÄsBIT|dˆ pHYsdd‹×y„tEXtSoftwarewww.inkscape.org›î<üIDATxœíœy\U‡¿ßíY B@–Z`ÐR@‰†°H©Á²Ä1¢@±ƒ  ÐD(Ë‚DÃRa‘ hÐÈb0cÀˆ`JB%²ïaË2÷çïŽIÞ¼×Ó=ÝÖb¾ª®ž¾÷¾sN¿óÞ}÷žszd› ¤™ÀWs͵½ï7¦Íôk“ÞM ÚÞu„vðn§]wÀÿ5cÆŒYì–k¾¿££ãóõÊês@ïØ xOA[ÝôMAm¦Ïm¦Ïm¦Ïm¦Ïm¦Ïm¦¦e¨¤ÁÀ‘ÀP`[àMài`)0Ïö-²±.$ Žö#³uPƒ"¯°ýÃFí*£ª$ξ@õPÁdIOW—Ù~»y&Ö†¤œœ ôo¢èÁM”ÕÂ)HÒv’f÷_¦¶8ÍNÀÀbIG6ÏÄž‘4X˜ô7óä·œnôIà~ºG+ke(0CÒÅ’6ÔNû|`Ÿ ¤«©¬çIû]Iïk‚ìS€ÓÔÐ2$}×J­ä¿W¨¤íYÀ€*ãWÏ“=Üv¶¯2~4ÙÕùÝlÙJÒ±5ŒxÙöœô÷y€ ƘŸìm„?6x|UÖ"fÛ”Œ[ œÜl{ź’>ŒŽ*Çž!énÛs{°eGàšZŒæHÚ Ø« 9ðÛOÔ(¯môtP–šœj{uQ§í¿c%]Ì&[¢æ™"é6Û± 6¯ËN_ýí8ù£Fê¿bÅŠn+@ÛW.Z´è›EÇ„4GŸ_"ó*Û'—üœ’ûÈœøbA÷.Àa=Éè›–´ß×]-!{“Ýþy–’­«kÆö l zL]–ÕÆ %í­pvKÀWJúÆØ~£^¶ït’4¤^y=ð/²yž¯Iš ió&ëk:ý€O´/¶ý‡äv£ tí Ìé>€Èµ°ÀöJI·‡æúSó$-«Q¦7€eÀÀ¶_®ñØ^Óâ‡æÂåÞQÒ^¤«‹Õ¶Ÿí…®Óýéž"|¸Ny#È6¡H:ø±[X»(^zþ»¡¶_Þ*è*[æ6¢k9Ù¦¯Ù & mÜ$i£È2E ‹æÕz)Zv-C_+èëõ|mûÀ™¤©©ÉD¶o - HÚšâõsé½hªÚHØÂöyd+ºGz+£ cS˜¦é´*XVVóLz/šâ‘Í¿½^ÃÛ^$i7²Àܧ©?0‚lÏRÄô>@Ɉ#Fcóí­r@Ñš%kîóKŽ݈bÛIO¯’ön¶Èuí/i í¢g[- NÌ76} ’´ÅwÀ¶_°ý(°¤`ÌQ’h¶Mõ`û^àÚ‚®þÀ𭝩HÕ_–tÿ<÷¹,ðve ²µ“¢$´ ;Ö4¤+÷~Š×ú~“kû YÔ2ÏPàAI£›e[/Èoìº(Šs5Dô“¤éÀ-”o´&æ73)o|zÉøí€›%]/i¯V'uº´©¤ã¯t¿<ÕleáÃ$íÞñCÈ‚xÃz÷#Û¿+ê°}}Jü§äØCÒëuIO³vÿ°ØözA?IÉ@ðQÊ‹lgÛ^Ó ün”9àcéÕ(¿%«ª¨Ædެ¶ÄÌúóïÀ‚1;{Öe]í¬&˼5VÞÚÓ€ƒ{J¤þƒKZhK£L²ýx+·Â/cS"§¦[Öv§í d{€gz¿Y œiû¢V)h¦^.†ÙîèÛ3€O6ѶÞð02…8ZFÙ3à²Ê‡2L¶*x޵ñó»›ñ²ý&YÀ9’v>GV&³-Ùs@dÙº<å¤{­š,°œl§~W+ºyÊp‰í²<ñÃöÃÔXVbûràòÖZ”cM®¯R©¼½`Á‚w†ža0`À€•«V­ê|$ß'2Ïç™ô¿à€w}åém¦Ïm¦§òô³BƒbŒÏ·Ø^Bx,ÆXožµn$}Ïö”ÆBXoÓc|Éö… êBø>°CŒñÛWV{05…Âë¢ê i\Œñ:àUI]Uù1Ð*þY㸻bŒ×Æ_¶Ž1^K÷À_)’Ž”¯à „pnŒñ…ãId+¬j<XÒ%MªUw.xM´¤gS mSI¯KZ |CÒ|àÛ©¿B¸XÒ0.µï*iÙ=v´$µŸ%é÷@ÿÂdàÈtìÒÔ$Í•t'0¸_ !\œdͶFJš•;ѓà ämB¸AÒ=ÀûÓØsºì#«›ä?–¾×!„RÿÆ’$+X> 8±ÈîZ¶=©³³sbú¼ÆöŒÃ1 Â'bŒw¦þ¶× ŠÍKï»KZh{•íe@§¤m’‚™¶ß‰1¾B®¾Çv´}’¤_ÙžÞ•U«á¶GV*•™éä|X$iYá>I#zøÒ+:;;±=]ÒŸ$Õûß\†CB×¥ÜFaU`9áTòQ•ãb²èél²ÍFQºq‰íã ûI‘¤-(¯í\ÂÙ1ÆS%OWðÊ[ é½rí$í.éj²$üª<×lw„N¶Š1®6QÆÞ¶oÏ _m»KÖ£ÀS1Æ£]¥¸¹Ù¶>_ÃST·Si’æT*•]%íœÕ§/ò—J¥òxa®¤-mŸj;JEåCk‘tð°íK%)„0øV 6ý]©T:€51ÆéÀ`I§HZcû€ã\I—JzÍö¬®ƒ+•Ê à²~[ŒñiI·Júp€¤·r9&ÈâGÛT*•ɶϔôÓÂ5•Jåõã?lw«/úã³¶n+BIEND®B`‚phoronix-test-suite/pts-core/results-viewer/pts.js0000644000175000017500000000210411564533734022526 0ustar michaelmichael function switchShow(i) { if(document.getElementById(i).style.display == "none") showObject(i); else hideObject(i); } function hideObject(i) { document.getElementById(i).style.display = "none"; } function showObject(i) { document.getElementById(i).style.display = "block"; } function setImagesFromURL() { var html = ""; var pf = location.href; pf = pf.substring(pf.search(/#/) + 1); var imgarray = pf.split(","); for(i = 0; i < imgarray.length; i++) { var exsplit = imgarray[i].split("."); if(exsplit[1] == "svg") html += "

"; else html += "

"; } document.getElementById("pts_monitor").innerHTML = html; } function boldBodyComponents() { var el = document.getElementsByName('pts_column_body'); for(var i = 0; i < el.length; i++) { el[i].innerHTML = el[i].innerHTML.replace(/:/, ":"); el[i].innerHTML = el[i].innerHTML.replace(/,/, ", "); el[i].innerHTML = "" + el[i].innerHTML; } } phoronix-test-suite/pts-core/results-viewer/horizontal-nav-bg-hover.png0000644000175000017500000000065711564533734026565 0ustar michaelmichael‰PNG  IHDR $?ö<¬sRGB®Îé pHYs  šœtIMEÚàÄRAIDAT8Ëu“1rÄ0 ½ôþÿl R>§ˆ{$бT>Ÿÿ¯DuvQ=U¢© X p´àý@!(áX N°[€S{/!LH œ‘qPs£”séþ9­ÏÕ÷Ï”?Õ U5‰’plÝÜkOB+‰õxµåOÖ'yM&$Á§yrd;g|âÒceLËã¬Bñ´%D1æÊÈ"[×ÞPn.’N›LVš]×k /Rc>[òì/fÉh9µÛ²0⦠6#íëÔ‹;t%qs™“ÓñÀậ?×RÌXרßqÈ«Xçlf™ Ð×zD²É}pç8#?ÄM>Ýf“IZñ…Z ‘S#_Ðë]Ö–/ÑÇ9¯ƒÏ¬åj{žƒ1G«¯[îPÏÎ"ùŽaÜöd§å>ùËãA¦¿²/€‹á¨½©IEND®B`‚phoronix-test-suite/pts-core/results-viewer/horizontal-nav-bg.png0000644000175000017500000000075411740171657025440 0ustar michaelmichael‰PNG  IHDR $°”«ûsRGB®ÎébKGDV•žW{ pHYs  šœtIMEÜ 7ØÊa0lIDAT8Ë”Kn1 CÉ@è{³^ׯ }¬IºèÉ lYIÉþúþAÿx^úçB’VR×»—l âÜÍ @ȹLž„üg•¬·Ö¹˜ÙQæóE ‘ðdNU•ÂȺX³á¼Ê8ÉÄ ôNùYkz­S›Ý¨·Þi#¤Ð©b¼l”#a+¦˜ª¦xI±´ ªÍ®½mK:9 TçSÛ!Ó@¦ù°F¢§ÐÎ îÎ^WA¶<'õÚTJ¡Ü³€û’:3—¼Ý(žIRêHi¹úöÊZI‚ÃíìY¿ît«å%ž·ºÕ®“–ôê©ëþUËÌi$ývÄáí*®»IEND®B`‚phoronix-test-suite/pts-core/results-viewer/favicon.ico0000644000175000017500000000217611564533734023514 0ustar michaelmichael h(  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûß“ÿÿÿÿÿÿÿÿî?ÿÿ*¨ÿïÿÿ©ÿ•ÿÿ,ÿàúÿÿùÜÿ)+ÿâÿ¨«ÿ—íÿ©+-«ÿò<ïÿÿÿÿÿñD“áùá–ÏÿÏÿÏÿÏÿÏÿÀ?ÀÏÏÇÏçÏçÏçÇÇãðø?phoronix-test-suite/pts-core/results-viewer/background-pattern.png0000644000175000017500000000027311740172301025650 0ustar michaelmichael‰PNG  IHDRýÔšssRGB®ÎébKGD?m÷¢÷ pHYs  šœtIMEÜ~\£tEXtCommentCreated with GIMPWIDAT×c|ÿþ=!ÆÑ°P-IEND®B`‚phoronix-test-suite/pts-core/openbenchmarking.org/openbenchmarking-mime.xml0000644000175000017500000000047311564533734027452 0ustar michaelmichael An OpenBenchmarking.org launcher for test profiles, suites, and stored results. phoronix-test-suite/pts-core/static/user-config-defaults.xml0000644000175000017500000000473211733076647024435 0ustar michaelmichael TRUE TRUE TRUE 3 FALSE TRUE DEFAULT toggle_screensaver, update_checker, graphics_event_checker FALSE TRUE FALSE FALSE ~/.phoronix-test-suite/installed-tests/ ~/.phoronix-test-suite/download-cache/ TRUE FALSE FALSE ~/.phoronix-test-suite/test-results/ FALSE TRUE TRUE 20 3.50 TRUE FALSE TRUE TRUE TRUE TRUE TRUE FALSE FALSE 20 phoronix-test-suite/pts-core/static/bash_completion0000644000175000017500000000044211267365263022745 0ustar michaelmichaelhave phoronix-test-suite && _phoronix-test-suite-show() { local cur COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} COMPREPLY=($( compgen -W "$(phoronix-test-suite dump-possible-options)" -- "$cur" )) } complete -F _phoronix-test-suite-show phoronix-test-suite phoronix-test-suite/pts-core/static/short-description.txt0000644000175000017500000000123111154367152024064 0ustar michaelmichaelThe Phoronix Test Suite is the most comprehensive testing and benchmarking platform available for the Linux operating system. This software is designed to effectively carry out both qualitative and quantitative benchmarks in a clean, reproducible, and easy-to-use manner. The Phoronix Test Suite consists of a lightweight processing core (pts-core) with each benchmark consisting of an XML-based profile with related resource scripts. The process from the benchmark installation, to the actual benchmarking, to the parsing of important hardware and software components is heavily automated and completely repeatable, asking users only for confirmation of actions. phoronix-test-suite/pts-core/static/phoronix-test-suite-launcher.desktop0000644000175000017500000000032211701100321026764 0ustar michaelmichael[Desktop Entry] Name=Phoronix Test Suite Launcher Exec=phoronix-test-suite openbenchmarking-launcher %f NoDisplay=true StartupNotify=true MimeType=application/x-openbenchmarking; Terminal=true Type=Application phoronix-test-suite/pts-core/static/phoronix-test-suite.desktop0000644000175000017500000000054411701100321025173 0ustar michaelmichael[Desktop Entry] Name=Phoronix Test Suite GenericName=Phoronix Test Suite Benchmarking Utility Comment=An Automated, Open-Source Testing Framework Comment[fr]=Outil pour étalonner les performances de votre ordinateur Exec=phoronix-test-suite interactive StartupNotify=true Icon=phoronix-test-suite Terminal=true Type=Application Categories=System;Monitor; phoronix-test-suite/pts-core/modules/toggle_screensaver.php0000644000175000017500000002023512222545271024420 0ustar michaelmichael. */ class toggle_screensaver extends pts_module_interface { const module_name = 'Toggle Screensaver'; const module_version = '1.5.0'; const module_description = 'This module toggles the system\'s screensaver while the Phoronix Test Suite is running. At this time, the GNOME and KDE screensavers are supported.'; const module_author = 'Phoronix Media'; static $xdg_screensaver_available = false; static $xset = false; static $screensaver_halted = false; static $gnome2_screensaver_halted = false; static $gnome3_screensaver_halted = false; static $gnome3_screensaver_halted_old = false; static $kde_screensaver_halted = false; static $gnome_gconftool = false; static $xfce_screensaver_halted = false; static $sleep_display_ac = false; public static function module_environmental_variables() { return array('HALT_SCREENSAVER'); } public static function __startup() { $halt_screensaver = pts_module::read_variable('HALT_SCREENSAVER'); if(!empty($halt_screensaver) && !pts_strings::string_bool($halt_screensaver)) { return pts_module::MODULE_UNLOAD; } // GNOME Screensaver? if(($gt = pts_client::executable_in_path('gconftool')) != false || ($gt = pts_client::executable_in_path('gconftool-2')) != false) { self::$gnome_gconftool = $gt; } if(self::$gnome_gconftool != false) { $is_gnome_screensaver_enabled = trim(shell_exec(self::$gnome_gconftool . ' -g /apps/gnome-screensaver/idle_activation_enabled 2>&1')); if($is_gnome_screensaver_enabled == 'true') { // Stop the GNOME Screensaver shell_exec(self::$gnome_gconftool . ' --type bool --set /apps/gnome-screensaver/idle_activation_enabled false 2>&1'); self::$gnome2_screensaver_halted = true; } $sleep_display_ac = trim(shell_exec(self::$gnome_gconftool . ' -g /apps/gnome-power-manager/timeout/sleep_display_ac 2>&1')); if($sleep_display_ac != 0) { // Don't sleep the display when on AC power shell_exec(self::$gnome_gconftool . ' --type int --set /apps/gnome-power-manager/timeout/sleep_display_ac 0 2>&1'); self::$sleep_display_ac = $sleep_display_ac; } } if(pts_client::executable_in_path('qdbus')) { // KDE Screensaver? $is_kde_screensaver_enabled = trim(shell_exec('qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.GetActive 2>&1')); if($is_kde_screensaver_enabled == 'true') { // Stop the KDE Screensaver shell_exec('qdbus org.freedesktop.ScreenSaver /ScreenSaver SimulateUserActivity 2>&1'); self::$kde_screensaver_halted = true; } } if(pts_client::executable_in_path('gsettings')) { // GNOME 3.x Screensaver? $is_gnome3_screensaver_enabled = trim(shell_exec('gsettings get org.gnome.desktop.session idle-delay 2>&1')); if(stripos($is_gnome3_screensaver_enabled, 'no such key') === false && pts_strings::last_in_string($is_gnome3_screensaver_enabled) > 0) { // Stop the GNOME 3.x Screensaver shell_exec('gsettings set org.gnome.desktop.session idle-delay 0 2>&1'); self::$gnome3_screensaver_halted = pts_strings::last_in_string($is_gnome3_screensaver_enabled); } // This GNOME3 GSettings method is deprecated on distributions like GNOME 3.8 with Fedora 19 $is_gnome3_screensaver_enabled_old = trim(shell_exec('gsettings get org.gnome.desktop.screensaver idle-activation-enabled 2>&1')); if($is_gnome3_screensaver_enabled_old == 'true') { // Stop the GNOME 3.x Screensaver shell_exec('gsettings set org.gnome.desktop.screensaver idle-activation-enabled false 2>&1'); self::$gnome3_screensaver_halted_old = true; } // GNOME 3.x Sleep Dispaly? $is_gnome3_sleep = trim(shell_exec('gsettings get org.gnome.settings-daemon.plugins.power sleep-display-ac 2>&1')); if($is_gnome3_sleep > 0) { // Stop the GNOME 3.x Display Sleep shell_exec('gsettings set org.gnome.settings-daemon.plugins.power sleep-display-ac 0 2>&1'); self::$sleep_display_ac = $is_gnome3_sleep; } } if(pts_client::executable_in_path('xfconf-query')) { $is_xfce_screensaver_enabled = stripos(shell_exec('xfconf-query -c xfce4-session -p /startup/screensaver/enabled 2>&1'), 'false') !== false; if($is_xfce_screensaver_enabled) { shell_exec('xfconf-query -c xfce4-session -n -t bool -p /startup/screensaver/enabled -s false 2>&1'); self::$xfce_screensaver_halted = true; } } if(getenv('DISPLAY') != false && (self::$xset = pts_client::executable_in_path('xset'))) { shell_exec('xset s off 2>&1'); } else if(getenv('DISPLAY') == false && pts_client::executable_in_path('setterm')) { shell_exec('setterm -powersave off -blank 0 2>&1'); } if(self::$gnome2_screensaver_halted || self::$gnome3_screensaver_halted || self::$gnome3_screensaver_halted_old || self::$kde_screensaver_halted || self::$xfce_screensaver_halted) { self::$screensaver_halted = true; } if(($xdg = pts_client::executable_in_path('xdg-screensaver')) == false) { self::$xdg_screensaver_available = $xdg; } if(($xscreensaver = pts_client::executable_in_path('xscreensaver-command'))) { shell_exec($xscreensaver . ' -exit 2>&1'); } } public static function __shutdown() { if(self::$sleep_display_ac) { // Restore the screen sleep state when on AC power if(pts_client::executable_in_path('gsettings')) { shell_exec('gsettings set org.gnome.settings-daemon.plugins.power sleep-display-ac ' . self::$sleep_display_ac . ' 2>&1'); } else { shell_exec(self::$gnome_gconftool . ' --type int --set /apps/gnome-power-manager/timeout/sleep_display_ac ' . self::$sleep_display_ac . ' 2>&1'); } } if(self::$gnome2_screensaver_halted == true) { // Restore the GNOME Screensaver shell_exec(self::$gnome_gconftool . ' --type bool --set /apps/gnome-screensaver/idle_activation_enabled true 2>&1'); } if(self::$gnome3_screensaver_halted) { // Restore the GNOME Screensaver shell_exec('gsettings set org.gnome.desktop.session idle-delay ' . self::$gnome3_screensaver_halted . ' 2>&1'); } if(self::$gnome3_screensaver_halted_old == true) { // Restore the GNOME Screensaver shell_exec('gsettings set org.gnome.desktop.screensaver idle-activation-enabled true 2>&1'); } if(self::$xfce_screensaver_halted) { shell_exec('xfconf-query -c xfce4-session -n -t bool -p /startup/screensaver/enabled -s true 2>&1'); } if(self::$kde_screensaver_halted == true) { // Restore the KDE Screensaver shell_exec('qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.SetActive true 2>&1'); } if(self::$xset) { shell_exec('xset s default'); } if(getenv('DISPLAY') == false && pts_client::executable_in_path('setterm')) { shell_exec('setterm -reset 2>&1'); } } public static function xdg_screensaver_reset() { if(!self::$screensaver_halted && self::$xdg_screensaver_available) { shell_exec(self::$xdg_screensaver_available . ' reset 2>&1'); } if(($xscreensaver = pts_client::executable_in_path('xscreensaver-command'))) { shell_exec($xscreensaver . ' -deactivate 2>&1'); } } public static function __pre_option_process() { self::xdg_screensaver_reset(); } public static function __pre_run_process() { self::xdg_screensaver_reset(); } public static function __pre_test_run() { self::xdg_screensaver_reset(); } public static function __post_run_process() { self::xdg_screensaver_reset(); } } ?> phoronix-test-suite/pts-core/modules/phoromatic.php0000644000175000017500000006245212202234007022701 0ustar michaelmichael. */ class phoromatic extends pts_module_interface { const module_name = 'Phoromatic Client'; const module_version = '2.0.0'; const module_description = 'The Phoromatic client is used for connecting to a Phoromatic server (Phoromatic.com or a locally run server) to facilitate the automatic running of tests, generally across multiple test nodes in a routine manner. For more details visit http://www.phoromatic.com/'; const module_author = 'Phoronix Media'; static $phoromatic_server_build = false; static $phoromatic_host = null; static $phoromatic_account = null; static $phoromatic_verifier = null; static $phoromatic_system = null; static $openbenchmarking_upload_json = null; public static function module_info() { return 'The Phoromatic module contains the client support for interacting with Phoromatic and Phoromatic Tracker services. A public, free reference implementation of Phoromatic can be found at http://www.phoromatic.com/. A commercial version is available to enterprise customers for installation onto their intranet. For more information, contact Phoronix Media.'; } public static function module_setup() { return array( new pts_module_option('remote_host', 'Enter the URL to host', 'HTTP_URL', 'http://www.phoromatic.com/'), new pts_module_option('remote_account', 'Enter the account code', 'ALPHA_NUMERIC'), new pts_module_option('remote_verifier', 'Enter the verification code', 'ALPHA_NUMERIC'), new pts_module_option('system_description', 'Enter a short (optional) description for this system', null, null, null, false) ); } public static function module_setup_validate($options) { if(substr($options['remote_host'], -14) != 'phoromatic.php') { $options['remote_host'] = pts_strings::add_trailing_slash($options['remote_host']) . 'phoromatic.php'; } $server_response = phoromatic::upload_to_remote_server(array( 'r' => 'setup', 'h' => phodevi::system_hardware(true), 's' => phodevi::system_software(true), 'o' => phodevi::read_property('system', 'hostname'), 'sys_desc' => $options['system_description'] ), $options['remote_host'], $options['remote_account'], $options['remote_verifier']); $returned_id = self::read_xml_value($server_response, 'PhoronixTestSuite/Phoromatic/General/Response'); unset($options['system_description']); // No reason to have this locally just pass it to the server if(!empty($returned_id)) { $options['remote_system'] = $returned_id; echo PHP_EOL . 'Run Phoromatic by entering: phoronix-test-suite phoromatic.start' . PHP_EOL; } else { echo PHP_EOL . 'Configuration Failed!' . PHP_EOL; $options = array(); } return $options; } public static function user_commands() { return array( 'start' => 'user_start', 'user_system_return' => 'user_system_return', 'upload_results' => 'upload_unscheduled_results', 'clone_results' => 'clone_results', 'system_schedule' => 'system_schedule', 'system_schedule_today' => 'system_schedule_today', 'send_message' => 'report_message_to_server' ); } // // User Run Commands // public static function user_start() { if(pts_client::create_lock(PTS_USER_PATH . 'phoromatic_lock') == false) { pts_client::$display->generic_error('Phoromatic is already running.'); return false; } if(!phoromatic::phoromatic_setup_module()) { return false; } phoromatic::user_system_process(); } public static function upload_unscheduled_results($to_upload) { if(!phoromatic::phoromatic_setup_module()) { return false; } if(!isset($to_upload[0]) || pts_result_file::is_test_result_file($to_upload[0]) == false) { echo PHP_EOL . 'No test result file was found to upload.' . PHP_EOL; return false; } phoromatic::upload_unscheduled_test_results($to_upload[0]); } public static function clone_results($to_clone) { if(!phoromatic::phoromatic_setup_module()) { return false; } if(!isset($to_clone[0]) || empty($to_clone[0])) { echo PHP_EOL . 'No clone string was provided.' . PHP_EOL; return false; } $server_response = phoromatic::upload_to_remote_server(array( 'r' => 'clone_test_results', 'i' => $to_clone[0] )); switch(self::read_xml_value($server_response, 'PhoronixTestSuite/Phoromatic/General/Response')) { case 'TRUE': $identifier = 'phoromatic-clone-' . str_replace(array('_', ':'), null, $to_clone[0]); pts_client::save_test_result($identifier . '/composite.xml', $server_response); // TODO: regenerate the XML so that the Phoromatic response bits are not included echo PHP_EOL . 'Result Saved To: ' . PTS_SAVE_RESULTS_PATH . $identifier . '/composite.xml' . PHP_EOL . PHP_EOL; pts_client::display_web_page(PTS_SAVE_RESULTS_PATH . $identifier . '/index.html'); break; case 'SETTING_DISABLED': echo PHP_EOL . 'You need to enable this support from your Phoromatic account web interface.' . PHP_EOL; break; default: case 'ERROR': echo PHP_EOL . 'An Error Occurred.' . PHP_EOL; break; } } public static function system_schedule() { if(!phoromatic::phoromatic_setup_module()) { return false; } $server_response = phoromatic::upload_to_remote_server(array( 'r' => 'system_schedule' )); $schedule_xml = new nye_XmlReader($server_response); $schedule_titles = $schedule_xml->getXmlArrayValues('PhoronixTestSuite/Phoromatic/Schedules/TestSchedule/Title'); $schedule_description = $schedule_xml->getXmlArrayValues('PhoronixTestSuite/Phoromatic/Schedules/TestSchedule/Description'); $schedule_active_on = $schedule_xml->getXmlArrayValues('PhoronixTestSuite/Phoromatic/Schedules/TestSchedule/ActiveOn'); $schedule_start_time = $schedule_xml->getXmlArrayValues('PhoronixTestSuite/Phoromatic/Schedules/TestSchedule/RunAt'); if(count($schedule_titles) == 0) { echo PHP_EOL . 'No test schedules for this system were found on the Phoromatic Server.' . PHP_EOL; } else { for($i = 0; $i < count($schedule_titles); $i++) { echo self::phoromatic_schedule_entry_string($schedule_titles[$i], $schedule_description[$i], $schedule_start_time[$i], $schedule_active_on[$i]); } } echo PHP_EOL; } public static function system_schedule_today() { if(!phoromatic::phoromatic_setup_module()) { return false; } $server_response = phoromatic::upload_to_remote_server(array( 'r' => 'system_schedule' )); $schedule_xml = new nye_XmlReader($server_response); $schedule_titles = $schedule_xml->getXmlArrayValues('PhoronixTestSuite/Phoromatic/Schedules/TestSchedule/Title'); $schedule_description = $schedule_xml->getXmlArrayValues('PhoronixTestSuite/Phoromatic/Schedules/TestSchedule/Description'); $schedule_active_on = $schedule_xml->getXmlArrayValues('PhoronixTestSuite/Phoromatic/Schedules/TestSchedule/ActiveOn'); $schedule_start_time = $schedule_xml->getXmlArrayValues('PhoronixTestSuite/Phoromatic/Schedules/TestSchedule/RunAt'); if(count($schedule_titles) == 0) { echo PHP_EOL . 'No test schedules for this system were found on the Phoromatic Server.' . PHP_EOL; } else { for($i = 0; $i < count($schedule_titles); $i++) { if($schedule_active_on[$i][(date('w'))] != 1) { continue; } echo self::phoromatic_schedule_entry_string($schedule_titles[$i], $schedule_description[$i], $schedule_start_time[$i], $schedule_active_on[$i]); } } echo PHP_EOL; } public static function send_message_to_server($msg) { if(!phoromatic::phoromatic_setup_module()) { return false; } if(empty($msg)) { echo PHP_EOL . 'Pass the message as the first argument.' . PHP_EOL; return false; } if(self::report_warning_to_phoromatic('MESSAGE: ' . implode(' ', $msg))) { echo PHP_EOL . 'Message Sent To Phoromatic Server.' . PHP_EOL; } else { echo PHP_EOL . 'Message Failed To Send.' . PHP_EOL; } } // // Core Functions // public static function user_system_process() { define('PHOROMATIC_PROCESS', true); $last_communication_minute = date('i'); $communication_attempts = 0; static $current_hw = null; static $current_sw = null; if(define('PHOROMATIC_START', true)) { echo PHP_EOL . 'Registering Status With Phoromatic Server @ ' . date('H:i:s') . PHP_EOL; $times_tried = 0; do { if($times_tried > 0) { echo PHP_EOL . 'Connection to server failed. Trying again in 60 seconds...' . PHP_EOL; sleep(60); } $update_sd = phoromatic::update_system_details(); $times_tried++; } while(!$update_sd && $times_tried < 5); if(!$update_sd) { echo 'Server connection still failed. Exiting...' . PHP_EOL; return false; } $current_hw = phodevi::system_hardware(true); $current_sw = phodevi::system_software(true); echo PHP_EOL . 'Idling 30 seconds for system to settle...' . PHP_EOL; sleep(30); } do { $exit_loop = false; echo PHP_EOL . 'Checking Status From Phoromatic Server @ ' . date('H:i:s'); if($last_communication_minute == date('i') && $communication_attempts > 2) { // Something is wrong, Phoromatic shouldn't be communicating with server more than three times a minute $response = 'idle'; } else { $server_response = phoromatic::upload_to_remote_server(array('r' => 'status_check')); $xml_parser = new nye_XmlReader($server_response); $response = $xml_parser->getXMLValue('PhoronixTestSuite/Phoromatic/General/Response'); if(date('i') != $last_communication_minute) { $last_communication_minute = date('i'); $communication_attempts = 0; } $communication_attempts++; } if($response != null) { echo ' [' . $response . ']' . PHP_EOL; } switch($response) { case 'benchmark': $test_flags = pts_c::auto_mode; do { $suite_identifier = 'phoromatic-' . rand(1000, 9999); } while(is_file(PTS_TEST_SUITE_PATH . 'local/' . $suite_identifier . '/suite-definition.xml')); pts_file_io::mkdir(PTS_TEST_SUITE_PATH . 'local/' . $suite_identifier); file_put_contents(PTS_TEST_SUITE_PATH . 'local/' . $suite_identifier . '/suite-definition.xml', $server_response); $phoromatic_schedule_id = $xml_parser->getXMLValue('PhoronixTestSuite/Phoromatic/General/ID'); $phoromatic_results_identifier = $xml_parser->getXMLValue('PhoronixTestSuite/Phoromatic/General/SystemName'); $phoromatic_trigger = $xml_parser->getXMLValue('PhoronixTestSuite/Phoromatic/General/Trigger'); self::$openbenchmarking_upload_json = null; $suite_identifier = 'local/' . $suite_identifier; if(pts_strings::string_bool($xml_parser->getXMLValue('PhoronixTestSuite/Phoromatic/General/RunInstallCommand', 'TRUE'))) { phoromatic::set_user_context($xml_parser->getXMLValue('PhoronixTestSuite/Phoromatic/General/SetContextPreInstall'), $phoromatic_trigger, $phoromatic_schedule_id, 'INSTALL'); if(pts_strings::string_bool($xml_parser->getXMLValue('PhoronixTestSuite/Phoromatic/General/ForceInstallTests', 'TRUE'))) { $test_flags |= pts_c::force_install; } pts_client::set_test_flags($test_flags); pts_test_installer::standard_install($suite_identifier); } phoromatic::set_user_context($xml_parser->getXMLValue('PhoronixTestSuite/Phoromatic/General/SetContextPreRun'), $phoromatic_trigger, $phoromatic_schedule_id, 'INSTALL'); // Do the actual running if(pts_test_run_manager::initial_checks($suite_identifier)) { $test_run_manager = new pts_test_run_manager($test_flags); // Load the tests to run if($test_run_manager->load_tests_to_run($suite_identifier)) { if(pts_strings::string_bool($xml_parser->getXMLValue('PhoronixTestSuite/Phoromatic/General/UploadToGlobal', 'FALSE'))) { $test_run_manager->auto_upload_to_openbenchmarking(); pts_openbenchmarking_client::override_client_setting('UploadSystemLogsByDefault', pts_strings::string_bool($xml_parser->getXMLValue('PhoronixTestSuite/Phoromatic/General/UploadSystemLogs', 'TRUE'))); } // Save results? $save_identifier = date('Y-m-d H:i:s'); $test_run_manager->auto_save_results($save_identifier, $phoromatic_results_identifier, 'A Phoromatic run.'); // Run the actual tests $test_run_manager->pre_execution_process(); $test_run_manager->call_test_runs(); $test_run_manager->post_execution_process(); // Upload to Phoromatic pts_file_io::unlink(PTS_TEST_SUITE_PATH . $suite_identifier . '/suite-definition.xml'); // Upload test results if(is_file(PTS_SAVE_RESULTS_PATH . $test_run_manager->get_file_name() . '/composite.xml')) { phoromatic::update_system_status('Uploading Test Results'); $times_tried = 0; do { if($times_tried > 0) { echo PHP_EOL . 'Connection to server failed. Trying again in 60 seconds...' . PHP_EOL; sleep(60); } $uploaded_test_results = phoromatic::upload_test_results($test_run_manager->get_file_name(), $phoromatic_schedule_id, $phoromatic_results_identifier, $phoromatic_trigger, $xml_parser); $times_tried++; } while($uploaded_test_results == false && $times_tried < 5); if($uploaded_test_results == false) { echo 'Server connection failed. Exiting...' . PHP_EOL; return false; } if(pts_strings::string_bool($xml_parser->getXMLValue('PhoronixTestSuite/Phoromatic/General/ArchiveResultsLocally', 'TRUE')) == false) { pts_client::remove_saved_result_file($test_run_manager->get_file_name()); } } } } break; case 'exit': echo PHP_EOL . 'Phoromatic received a remote command to exit.' . PHP_EOL; phoromatic::update_system_status('Exiting Phoromatic'); pts_client::release_lock(PTS_USER_PATH . 'phoromatic_lock'); $exit_loop = true; break; case 'server_maintenance': // The Phoromatic server is down for maintenance, so don't bother updating system status and wait longer before checking back echo PHP_EOL . 'The Phoromatic server is currently down for maintenance. Waiting for service to be restored.' . PHP_EOL; sleep((15 - (date('i') % 15)) * 60); break; case 'SHUTDOWN': echo PHP_EOL . 'Shutting down the system.' . PHP_EOL; $exit_loop = true; shell_exec('poweroff'); // Currently assuming root break; case 'REBOOT': echo PHP_EOL . 'Rebooting the system.' . PHP_EOL; $exit_loop = true; shell_exec('reboot'); // Currently assuming root break; case 'idle': default: phoromatic::update_system_status('Idling, Waiting For Task'); sleep((10 - (date('i') % 10)) * 60); // Check with server every 10 minutes break; } if(phodevi::system_hardware(true) != $current_hw || phodevi::system_software(true) != $current_sw) { // Hardware and/or software has changed while PTS/Phoromatic has been running, update the Phoromatic Server echo 'Updating Installed Hardware / Software With Phoromatic Server' . PHP_EOL; phoromatic::update_system_details(); $current_hw = phodevi::system_hardware(true); $current_sw = phodevi::system_software(true); } } while($exit_loop == false); phoromatic::update_system_status('Offline'); } // // Process Functions // public static function __pre_test_install($test_identifier) { static $last_update_time = 0; if(time() > ($last_update_time + 600)) { phoromatic::update_system_status('Installing Tests'); $last_update_time = time(); } } public static function __pre_test_run($pts_test_result) { // TODO: need a way to get the estimated time remaining from the test_run_manager so we can pass that back to the update_system_status parameter so server can read it // TODO: report name of test identifier/run i.e. . ' For ' . PHOROMATIC_TITLE phoromatic::update_system_status('Running ' . $pts_test_result->test_profile->get_identifier()); } public static function __event_user_error($user_error) { // Report PTS user error warnings to Phoromatic server phoromatic::report_warning_to_phoromatic($user_error->get_error_string()); } public static function __event_results_saved($test_run_manager) { if(pts_module::read_variable('AUTO_UPLOAD_RESULTS_TO_PHOROMATIC') && pts_module::is_module_setup()) { phoromatic::upload_unscheduled_test_results($test_run_manager->get_file_name()); } } public static function __event_openbenchmarking_upload($json) { self::$openbenchmarking_upload_json = $json; } // // Other Functions // protected static function read_xml_value($file, $xml_option) { $xml_parser = new nye_XmlReader($file); return $xml_parser->getXMLValue($xml_option); } private static function set_user_context($context_script, $trigger, $schedule_id, $process) { if(!empty($context_script)) { if(!is_executable($context_script)) { if(($context_script = pts_client::executable_in_path($context_script)) == false || !is_executable($context_script)) { return false; } } $storage_path = pts_module::save_dir() . 'memory.pt2so'; $storage_object = pts_storage_object::recover_from_file($storage_path); // We check to see if the context was already set but the system rebooted or something in that script if($storage_object == false) { $storage_object = new pts_storage_object(true, true); } else if($storage_object->read_object('last_set_context_trigger') == $trigger && $storage_object->read_object('last_set_context_schedule') == $schedule_id && $storage_object->read_object('last_set_context_process') == $process) { // If the script already ran once for this trigger, don't run it again return false; } $storage_object->add_object('last_set_context_trigger', $trigger); $storage_object->add_object('last_set_context_schedule', $schedule_id); $storage_object->add_object('last_set_context_process', $process); $storage_object->save_to_file($storage_path); // Run the set context script exec($context_script . ' ' . $trigger); // Just simply return true for now, perhaps check exit code status and do something return true; } return false; } protected static function update_system_details() { $server_response = phoromatic::upload_to_remote_server(array('r' => 'update_system_details', 'h' => phodevi::system_hardware(true), 's' => phodevi::system_software(true))); self::$phoromatic_server_build = self::read_xml_value($server_response, 'PhoronixTestSuite/Phoromatic/Server/ServerBuild'); return self::read_xml_value($server_response, 'PhoronixTestSuite/Phoromatic/General/Response') == 'TRUE'; } protected static function update_system_status($current_task, $estimated_time_remaining = 0) { $server_response = phoromatic::upload_to_remote_server(array('r' => 'update_system_status', 'a' => $current_task, 'time' => $estimated_time_remaining)); return self::read_xml_value($server_response, 'PhoronixTestSuite/Phoromatic/General/Response') == 'TRUE'; } protected static function report_warning_to_phoromatic($warning) { $server_response = phoromatic::upload_to_remote_server(array('r' => 'report_pts_warning', 'a' => $warning)); return self::read_xml_value($server_response, 'PhoronixTestSuite/Phoromatic/General/Response') == 'TRUE'; } private static function capture_test_logs($save_identifier, &$xml_parser = null) { $data = array('system-logs' => null, 'test-logs' => null); if(is_dir(PTS_SAVE_RESULTS_PATH . $save_identifier . '/system-logs/') && ($xml_parser == null || $xml_parser->getXMLValue('PhoronixTestSuite/Phoromatic/General/UploadSystemLogs', 'FALSE'))) { $system_logs_zip = pts_client::create_temporary_file(); pts_compression::zip_archive_create($system_logs_zip, PTS_SAVE_RESULTS_PATH . $save_identifier . '/system-logs/'); $data['system-logs'] = base64_encode(file_get_contents($system_logs_zip)); unlink($system_logs_zip); } if(is_dir(PTS_SAVE_RESULTS_PATH . $save_identifier . '/test-logs/') && ($xml_parser == null || $xml_parser->getXMLValue('PhoronixTestSuite/Phoromatic/General/UploadTestLogs', 'FALSE'))) { $test_logs_zip = pts_client::create_temporary_file(); pts_compression::zip_archive_create($test_logs_zip, PTS_SAVE_RESULTS_PATH . $save_identifier . '/test-logs/'); $data['test-logs'] = base64_encode(file_get_contents($test_logs_zip)); unlink($test_logs_zip); } return $data; } protected static function upload_test_results($save_identifier, $phoromatic_schedule_id, $results_identifier, $phoromatic_trigger, &$xml_parser = null) { $composite_xml = file_get_contents(PTS_SAVE_RESULTS_PATH . $save_identifier . '/composite.xml'); if(self::$openbenchmarking_upload_json != null && isset(self::$openbenchmarking_upload_json['openbenchmarking']['upload']['id'])) { $openbenchmarking_id = self::$openbenchmarking_upload_json['openbenchmarking']['upload']['id']; } else { $openbenchmarking_id = null; } $logs = self::capture_test_logs($save_identifier, $xml_parser); $server_response = phoromatic::upload_to_remote_server(array( 'r' => 'upload_test_results', 'c' => $composite_xml, 'i' => $phoromatic_schedule_id, 'ti' => $results_identifier, 'ts' => $phoromatic_trigger, 'sl' => $logs['system-logs'], 'tl' => $logs['test-logs'], 'ob' => $openbenchmarking_id, )); return self::read_xml_value($server_response, 'PhoronixTestSuite/Phoromatic/General/Response') == 'TRUE'; } protected static function upload_unscheduled_test_results($save_identifier) { $composite_xml = file_get_contents(PTS_SAVE_RESULTS_PATH . $save_identifier . '/composite.xml'); $logs = self::capture_test_logs($save_identifier); $server_response = phoromatic::upload_to_remote_server(array( 'r' => 'upload_test_results_unscheduled', 'c' => $composite_xml, 'i' => 0, 'ti' => 'Unknown', 'sl' => $logs['system-logs'], 'tl' => $logs['test-logs'] )); $xml_parser = new nye_XmlReader($server_response); switch($xml_parser->getXMLValue('PhoronixTestSuite/Phoromatic/General/Response')) { case 'TRUE': echo PHP_EOL . 'Uploaded To Phoromatic.' . PHP_EOL; break; case 'ERROR': echo PHP_EOL . 'An Error Occurred.' . PHP_EOL; break; case 'SETTING_DISABLED': echo PHP_EOL . 'You need to enable this support from your Phoromatic account web interface.' . PHP_EOL; break; } return $xml_parser->getXMLValue('PhoronixTestSuite/Phoromatic/General/Response') == 'TRUE'; } protected static function phoromatic_setup_module() { if(!pts_module::is_module_setup()) { echo PHP_EOL . 'You first must run:' . PHP_EOL . PHP_EOL . 'phoronix-test-suite module-setup phoromatic' . PHP_EOL . PHP_EOL; return false; } self::$phoromatic_host = pts_module::read_option('remote_host'); self::$phoromatic_account = pts_module::read_option('remote_account'); self::$phoromatic_verifier = pts_module::read_option('remote_verifier'); self::$phoromatic_system = pts_module::read_option('remote_system'); if(extension_loaded('openssl') == false) { // OpenSSL is not supported therefore no HTTPS support self::$phoromatic_host = str_replace('https://', 'http://', self::$phoromatic_host); } $phoromatic = 'phoromatic'; pts_module_manager::attach_module($phoromatic); return true; } protected static function phoromatic_schedule_entry_string($title, $description, $start_time, $active_on) { echo PHP_EOL . $title . ':' . PHP_EOL; echo "\t" . $description . PHP_EOL; echo "\t" . 'Runs at ' . $start_time . ' on ' . pts_strings::parse_week_string($active_on) . '.' . PHP_EOL; } // // Connection // protected static function upload_to_remote_server($to_post, $host = null, $account = null, $verifier = null, $system = null) { static $last_communication_minute = null; static $communication_attempts = 0; if($last_communication_minute == date('i') && $communication_attempts > 3) { // Something is wrong, Phoromatic shouldn't be communicating with server more than four times a minute return false; } else { if(date('i') != $last_communication_minute) { $last_communication_minute = date('i'); $communication_attempts = 0; } $communication_attempts++; } if($host != null) { //$host = $host; $to_post['aid'] = $account; $to_post['vid'] = $verifier; $to_post['sid'] = $system; } else if(self::$phoromatic_host != null) { $host = self::$phoromatic_host; $to_post['aid'] = self::$phoromatic_account; $to_post['vid'] = self::$phoromatic_verifier; $to_post['sid'] = self::$phoromatic_system; } else { echo PHP_EOL . 'Phoromatic isn\'t configured. Run: phoronix-test-suite module-setup phoromatic' . PHP_EOL . PHP_EOL; return; } $to_post['pts'] = PTS_VERSION; $to_post['pts_core'] = PTS_CORE_VERSION; $to_post['gsid'] = PTS_GSID; return pts_network::http_upload_via_post($host, $to_post); } } ?> phoronix-test-suite/pts-core/modules/system_monitor.php0000644000175000017500000003067011766646172023654 0ustar michaelmichael. */ class system_monitor extends pts_module_interface { const module_name = 'System Monitor'; const module_version = '3.1.0'; const module_description = 'This module contains sensor monitoring support.'; const module_author = 'Michael Larabel'; static $result_identifier = null; static $to_monitor = array(); static $monitor_test_count = 0; static $individual_test_run_request = null; static $successful_test_run_request = null; static $individual_test_run_offsets = null; static $individual_monitoring = null; private static $sensor_monitoring_frequency = 2; private static $test_run_timer = 0; private static $monitor_i915_energy = false; // special case of monitoring since it's not tapping Phodevi (right now at least) public static function module_environmental_variables() { return array('MONITOR', 'PERFORMANCE_PER_WATT'); } public static function module_info() { $info = null; $info .= PHP_EOL . 'Monitoring these sensors are as easy as running your normal Phoronix Test Suite commands but at the beginning of the command add: MONITOR= (example: MONITOR=cpu.temp,cpu.voltage phoronix-test-suite benchmark universe). If the PERFORMANCE_PER_WATT environment variable is set, a performance per Watt graph will also be added, assuming the system\'s power consumption can be monitored. Below are all of the sensors supported by this version of the Phoronix Test Suite.' . PHP_EOL . PHP_EOL; $info .= 'Supported Options:' . PHP_EOL . PHP_EOL; foreach(self::monitor_arguments() as $arg) { $info .= ' - ' . $arg . PHP_EOL; } return $info; } // // General Functions // public static function __run_manager_setup(&$test_run_manager) { $test_run_manager->force_results_save(); } public static function __pre_run_process(&$test_run_manager) { self::$result_identifier = $test_run_manager->get_results_identifier(); self::$individual_monitoring = pts_module::read_variable('MONITOR_INDIVIDUAL') !== '0'; self::$to_monitor = array(); $to_show = pts_strings::comma_explode(pts_module::read_variable('MONITOR')); $monitor_all = in_array('all', $to_show); if(pts_module::read_variable('PERFORMANCE_PER_WATT')) { // We need to ensure the system power consumption is being tracked to get performance-per-Watt pts_arrays::unique_push($to_show, 'sys.power'); self::$individual_monitoring = true; echo PHP_EOL . 'To Provide Performance-Per-Watt Outputs.' . PHP_EOL; } foreach(phodevi::supported_sensors() as $sensor) { if($monitor_all || in_array(phodevi::sensor_identifier($sensor), $to_show) || in_array('all.' . $sensor[0], $to_show)) { array_push(self::$to_monitor, $sensor); pts_module::save_file('logs/' . phodevi::sensor_identifier($sensor)); } } if(in_array('i915_energy', $to_show) && is_readable('/sys/kernel/debug/dri/0/i915_energy')) { // For now the Intel monitoring is a special case separate from the rest // of the unified sensor monitoring since we're not polling it every time but just pre/post test. self::$monitor_i915_energy = true; } if(count(self::$to_monitor) > 0) { echo PHP_EOL . 'Sensors To Be Logged:'; foreach(self::$to_monitor as &$sensor) { echo PHP_EOL . ' - ' . phodevi::sensor_name($sensor); } echo PHP_EOL; // Pad some idling sensor results at the start sleep((self::$sensor_monitoring_frequency * 4)); } pts_module::pts_timed_function('pts_monitor_update', self::$sensor_monitoring_frequency); } public static function __pre_test_run($test_run_request) { if(self::$individual_monitoring == false) { return; } self::$individual_test_run_request = clone $test_run_request; foreach(self::$to_monitor as $sensor) { $log_f = pts_module::read_file('logs/' . phodevi::sensor_identifier($sensor)); $offset = count(explode(PHP_EOL, $log_f)); self::$individual_test_run_offsets[phodevi::sensor_identifier($sensor)] = $offset; } // Just to pad in some idling into the run process sleep(self::$sensor_monitoring_frequency); if(self::$monitor_i915_energy) { // Just read i915_energy to reset the joule counter file_get_contents('/sys/kernel/debug/dri/0/i915_energy'); } self::$test_run_timer = time(); } public static function __post_test_run_success($test_run_request) { self::$successful_test_run_request = clone $test_run_request; } public static function __post_test_run_process(&$result_file_writer) { if((self::$individual_monitoring == false || count(self::$to_monitor) == 0) && self::$monitor_i915_energy == false) { return; } // The self::$test_run_timer to contain how long each individual test run lasted, should anything else past this point want to use the info... self::$test_run_timer = time() - self::$test_run_timer; // Let the system return to brief idling.. sleep(self::$sensor_monitoring_frequency); if(pts_module::read_variable('PERFORMANCE_PER_WATT')) { $sensor = array('sys', 'power'); $sensor_results = self::parse_monitor_log('logs/' . phodevi::sensor_identifier($sensor), self::$individual_test_run_offsets[phodevi::sensor_identifier($sensor)]); if(count($sensor_results) > 2 && self::$successful_test_run_request) { // Copy the value each time as if you are directly writing the original data, each succeeding time in the loop the used arguments gets borked $test_result = clone self::$successful_test_run_request; $process_perf_per_watt = true; $watt_average = array_sum($sensor_results) / count($sensor_results); switch(phodevi::read_sensor_unit($sensor)) { case 'Milliwatts': $watt_average = $watt_average / 1000; case 'Watts': break; default: $process_perf_per_watt = false; } if($process_perf_per_watt && $watt_average > 0 && $test_result->test_profile->get_display_format() == 'BAR_GRAPH') { $test_result->test_profile->set_identifier(null); //$test_result->set_used_arguments_description(phodevi::sensor_name('sys.power') . ' Monitor'); //$test_result->set_used_arguments(phodevi::sensor_name('sys.power') . ' ' . $test_result->get_arguments()); if($test_result->test_profile->get_result_proportion() == 'HIB') { $test_result->test_profile->set_result_scale($test_result->test_profile->get_result_scale() . ' Per Watt'); $test_result->set_result(pts_math::set_precision($test_result->get_result() / $watt_average)); $result_file_writer->add_result_from_result_object_with_value_string($test_result, $test_result->get_result()); } else if($test_result->test_profile->get_result_proportion() == 'LIB') { $test_result->test_profile->set_result_proportion('HIB'); $test_result->test_profile->set_result_scale('Performance Per Watt'); $test_result->set_result(pts_math::set_precision(1 / ($test_result->get_result() / $watt_average))); $result_file_writer->add_result_from_result_object_with_value_string($test_result, $test_result->get_result()); } } } } foreach(self::$to_monitor as $sensor) { $sensor_results = self::parse_monitor_log('logs/' . phodevi::sensor_identifier($sensor), self::$individual_test_run_offsets[phodevi::sensor_identifier($sensor)]); if(count($sensor_results) > 2) { // Copy the value each time as if you are directly writing the original data, each succeeding time in the loop the used arguments gets borked $test_result = clone self::$individual_test_run_request; $test_result->test_profile->set_identifier(null); $test_result->test_profile->set_result_proportion('LIB'); $test_result->test_profile->set_display_format('LINE_GRAPH'); $test_result->test_profile->set_result_scale(phodevi::read_sensor_unit($sensor)); $test_result->set_used_arguments_description(phodevi::sensor_name($sensor) . ' Monitor'); $test_result->set_used_arguments(phodevi::sensor_name($sensor) . ' ' . $test_result->get_arguments()); $result_file_writer->add_result_from_result_object_with_value_string($test_result, implode(',', $sensor_results), implode(',', $sensor_results)); } self::$individual_test_run_offsets[phodevi::sensor_identifier($sensor)] = array(); } if(self::$monitor_i915_energy) { $i915_energy = file_get_contents('/sys/kernel/debug/dri/0/i915_energy'); if(($uj = strpos($i915_energy, ' uJ'))) { $uj = substr($i915_energy, 0, $uj); $uj = substr($uj, (strrpos($uj, ' ') + 1)); if(is_numeric($uj)) { $test_result = clone self::$individual_test_run_request; $test_result->test_profile->set_identifier(null); $test_result->test_profile->set_result_proportion('LIB'); $test_result->test_profile->set_display_format('BAR_GRAPH'); $test_result->test_profile->set_result_scale('micro Joules'); $test_result->set_used_arguments_description('i915_energy Monitor'); $test_result->set_used_arguments('i915_energy ' . $test_result->get_arguments()); $result_file_writer->add_result_from_result_object_with_value_string($test_result, $uj); } } } self::$successful_test_run_request = null; self::$individual_test_run_request = null; self::$monitor_test_count++; // Let the system rest before jumping to next test... sleep((self::$sensor_monitoring_frequency * 6)); } public static function __event_results_process(&$test_run_manager) { echo PHP_EOL . 'Finishing System Sensor Monitoring Process' . PHP_EOL; sleep((self::$sensor_monitoring_frequency * 4)); foreach(self::$to_monitor as $sensor) { $sensor_results = self::parse_monitor_log('logs/' . phodevi::sensor_identifier($sensor)); pts_module::remove_file('logs/' . phodevi::sensor_identifier($sensor)); if(count($sensor_results) > 2 && self::$monitor_test_count > 1) { $test_profile = new pts_test_profile(); $test_result = new pts_test_result($test_profile); $test_result->test_profile->set_test_title(phodevi::sensor_name($sensor) . ' Monitor'); $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('LINE_GRAPH'); $test_result->test_profile->set_result_scale(phodevi::read_sensor_unit($sensor)); $test_result->set_used_arguments_description('Phoronix Test Suite System Monitoring'); $test_result->set_used_arguments(phodevi::sensor_identifier($sensor)); $test_run_manager->result_file_writer->add_result_from_result_object_with_value_string($test_result, implode(',', $sensor_results), implode(',', $sensor_results)); } } } public static function pts_monitor_update() { foreach(self::$to_monitor as $sensor) { $sensor_value = phodevi::read_sensor($sensor); if($sensor_value != -1 && pts_module::is_file('logs/' . phodevi::sensor_identifier($sensor))) { pts_module::save_file('logs/' . phodevi::sensor_identifier($sensor), $sensor_value, true); } } } private static function parse_monitor_log($log_file, $start_offset = 0) { $log_f = pts_module::read_file($log_file); $line_breaks = explode(PHP_EOL, $log_f); $results = array(); for($i = 0; $i < $start_offset && isset($line_breaks[$i]); $i++) { unset($line_breaks[$i]); } foreach($line_breaks as $line) { $line = trim($line); if(!empty($line) && $line >= 0) { array_push($results, $line); } } if(count($results) > 0 && max($results) == 0) { $results = array(); } return $results; } private static function monitor_arguments() { $args = array('all'); foreach(phodevi::available_sensors() as $sensor) { if(!in_array('all.' . $sensor[0], $args)) { array_push($args, 'all.' . $sensor[0]); } array_push($args, phodevi::sensor_identifier($sensor)); } return $args; } } ?> phoronix-test-suite/pts-core/modules/ekofisk.php0000644000175000017500000005532511620741041022174 0ustar michaelmichael. */ class ekofisk extends pts_module_interface { const module_name = 'OpenBenchmarking.org Ekofisk'; const module_version = '1.0.0'; const module_description = 'The Ekofisk client is used for connecting to OpenBenchmarking.org to facilitate the automatic running of tests, generally across multiple test nodes in a routine manner.'; const module_author = 'OpenBenchmarking.org'; static $phoromatic_server_build = false; public static function module_info() { return ''; } public static function user_commands() { return array( 'start' => 'user_start', 'user_system_return' => 'user_system_return', ); } // // User Run Commands // public static function user_start() { if(pts_client::create_lock(PTS_USER_PATH . 'ekofisk_lock') == false) { pts_client::$display->generic_error('Ekofisk is already running.'); return false; } if(pts_openbenchmarking_client::user_name() == null) { pts_client::$display->generic_error('You must be logged into your OpenBenchmarking.org account.'); return false; } $last_communication_minute = null; $communication_attempts = 0; do { $exit_loop = false; if($last_communication_minute != date('i')) { echo PHP_EOL . 'Checking State From Server @ ' . date('H:i:s'); } if($last_communication_minute == date('i') && $communication_attempts > 3) { // Something is wrong, Phoromatic shouldn't be communicating with server more than three times a minute $response = M_PHOROMATIC_RESPONSE_IDLE; } else { $server_response = self::make_server_request(array('ekofisk_task' => 'status_check')); $json = json_decode($server_response, true); $response = $json['openbenchmarking']['response']['ekofisk']; if(date('i') != $last_communication_minute) { $last_communication_minute = date('i'); $communication_attempts = 0; } $communication_attempts++; } echo ' [' . $response . ']' . PHP_EOL; switch($response) { case M_PHOROMATIC_RESPONSE_RUN_TEST: $test_flags = pts_c::auto_mode | pts_c::recovery_mode; do { $suite_identifier = 'phoromatic-' . rand(1000, 9999); } while(is_file(PTS_TEST_SUITE_PATH . 'local/' . $suite_identifier . '/suite-definition.xml')); file_put_contents(PTS_TEST_SUITE_PATH . 'local/' . $suite_identifier . '/suite-definition.xml', $server_response); $phoromatic_schedule_id = $xml_parser->getXMLValue(M_PHOROMATIC_ID); $phoromatic_results_identifier = $xml_parser->getXMLValue(M_PHOROMATIC_SYS_NAME); $phoromatic_trigger = $xml_parser->getXMLValue(M_PHOROMATIC_TRIGGER); if(pts_strings::string_bool($xml_parser->getXMLValue(M_PHOROMATIC_RUN_INSTALL_COMMAND, M_PHOROMATIC_RESPONSE_TRUE))) { phoromatic::set_user_context($xml_parser->getXMLValue(M_PHOROMATIC_SET_CONTEXT_PRE_INSTALL), $phoromatic_trigger, $phoromatic_schedule_id, 'INSTALL'); pts_client::set_test_flags($test_flags); pts_test_installer::standard_install($suite_identifier); } phoromatic::set_user_context($xml_parser->getXMLValue(M_PHOROMATIC_SET_CONTEXT_PRE_RUN), $phoromatic_trigger, $phoromatic_schedule_id, 'INSTALL'); // Do the actual running if(pts_test_run_manager::initial_checks($suite_identifier)) { $test_run_manager = new pts_test_run_manager($test_flags); // Load the tests to run if($test_run_manager->load_tests_to_run($suite_identifier)) { if(pts_strings::string_bool($xml_parser->getXMLValue(M_PHOROMATIC_UPLOAD_TO_GLOBAL, 'FALSE'))) { $test_run_manager->auto_upload_to_openbenchmarking(); } // Save results? $test_run_manager->auto_save_results(date('Y-m-d H:i:s'), $phoromatic_results_identifier, 'A Phoromatic run.'); // Run the actual tests $test_run_manager->pre_execution_process(); $test_run_manager->call_test_runs(); $test_run_manager->post_execution_process(); // Upload to Phoromatic pts_file_io::unlink(PTS_TEST_SUITE_PATH . 'local/' . $suite_identifier . '/suite-definition.xml'); // Upload test results if(is_file(PTS_SAVE_RESULTS_PATH . $save_identifier . '/composite.xml')) { phoromatic::update_system_status('Uploading Test Results'); $times_tried = 0; do { if($times_tried > 0) { echo PHP_EOL . 'Connection to server failed. Trying again in 60 seconds...' . PHP_EOL; sleep(60); } $uploaded_test_results = phoromatic::upload_test_results($save_identifier, $phoromatic_schedule_id, $phoromatic_results_identifier, $phoromatic_trigger); $times_tried++; } while($uploaded_test_results == false && $times_tried < 5); if($uploaded_test_results == false) { echo 'Server connection failed. Exiting...' . PHP_EOL; return false; } if(pts_strings::string_bool($xml_parser->getXMLValue(M_PHOROMATIC_ARCHIVE_RESULTS_LOCALLY, M_PHOROMATIC_RESPONSE_TRUE)) == false) { pts_client::remove_saved_result_file($save_identifier); } } } } break; case M_PHOROMATIC_RESPONSE_EXIT: echo PHP_EOL . 'Phoromatic received a remote command to exit.' . PHP_EOL; phoromatic::update_system_status('Exiting Phoromatic'); pts_client::release_lock(PTS_USER_PATH . 'phoromatic_lock'); $exit_loop = true; break; case M_PHOROMATIC_RESPONSE_SERVER_MAINTENANCE: // The Phoromatic server is down for maintenance, so don't bother updating system status and wait longer before checking back echo PHP_EOL . 'The Phoromatic server is currently down for maintenance. Waiting for service to be restored.' . PHP_EOL; sleep((15 - (date('i') % 15)) * 60); break; case M_PHOROMATIC_RESPONSE_SHUTDOWN: echo PHP_EOL . 'Shutting down the system.' . PHP_EOL; $exit_loop = true; shell_exec('poweroff'); // Currently assuming root break; case M_PHOROMATIC_RESPONSE_REBOOT: echo PHP_EOL . 'Rebooting the system.' . PHP_EOL; $exit_loop = true; shell_exec('reboot'); // Currently assuming root break; case M_PHOROMATIC_RESPONSE_IDLE: default: phoromatic::update_system_status('Idling, Waiting For Task'); sleep((10 - (date('i') % 10)) * 60); // Check with server every 10 minutes break; } if(phodevi::system_hardware(true) != $current_hw || phodevi::system_software(true) != $current_sw) { // Hardware and/or software has changed while PTS/Phoromatic has been running, update the Phoromatic Server echo 'Updating Installed Hardware / Software With Phoromatic Server' . PHP_EOL; phoromatic::update_system_details(); $current_hw = phodevi::system_hardware(true); $current_sw = phodevi::system_software(true); } } while($exit_loop == false); phoromatic::update_system_status('Offline'); } public static function upload_unscheduled_results($to_upload) { if(!phoromatic::phoromatic_setup_module()) { return false; } if(!isset($to_upload[0]) || pts_result_file::is_test_result_file($to_upload[0]) == false) { echo PHP_EOL . 'No test result file was found to upload.' . PHP_EOL; return false; } phoromatic::upload_unscheduled_test_results($to_upload[0]); } // // Core Functions // public static function user_system_process() { $last_communication_minute = date('i'); $communication_attempts = 0; static $current_hw = null; static $current_sw = null; if(define('PHOROMATIC_START', true)) { echo PHP_EOL . 'Registering Status With Phoromatic Server @ ' . date('H:i:s') . PHP_EOL; $times_tried = 0; do { if($times_tried > 0) { echo PHP_EOL . 'Connection to server failed. Trying again in 60 seconds...' . PHP_EOL; sleep(60); } $update_sd = phoromatic::update_system_details(); $times_tried++; } while(!$update_sd && $times_tried < 5); if(!$update_sd) { echo 'Server connection still failed. Exiting...' . PHP_EOL; return false; } $current_hw = phodevi::system_hardware(true); $current_sw = phodevi::system_software(true); echo PHP_EOL . 'Idling 30 seconds for system to settle...' . PHP_EOL; sleep(30); } do { $exit_loop = false; echo PHP_EOL . 'Checking Status From Phoromatic Server @ ' . date('H:i:s'); if($last_communication_minute == date('i') && $communication_attempts > 2) { // Something is wrong, Phoromatic shouldn't be communicating with server more than three times a minute $response = M_PHOROMATIC_RESPONSE_IDLE; } else { $server_response = phoromatic::upload_to_remote_server(array('r' => 'status_check')); $xml_parser = new nye_XmlReader($server_response); $response = $xml_parser->getXMLValue(M_PHOROMATIC_GEN_RESPONSE); if(date('i') != $last_communication_minute) { $last_communication_minute = date('i'); $communication_attempts = 0; } $communication_attempts++; } echo ' [' . $response . ']' . PHP_EOL; switch($response) { case M_PHOROMATIC_RESPONSE_RUN_TEST: $test_flags = pts_c::auto_mode | pts_c::recovery_mode; do { $suite_identifier = 'phoromatic-' . rand(1000, 9999); } while(is_file(PTS_TEST_SUITE_PATH . 'local/' . $suite_identifier . '/suite-definition.xml')); file_put_contents(PTS_TEST_SUITE_PATH . 'local/' . $suite_identifier . '/suite-definition.xml', $server_response); $phoromatic_schedule_id = $xml_parser->getXMLValue(M_PHOROMATIC_ID); $phoromatic_results_identifier = $xml_parser->getXMLValue(M_PHOROMATIC_SYS_NAME); $phoromatic_trigger = $xml_parser->getXMLValue(M_PHOROMATIC_TRIGGER); if(pts_strings::string_bool($xml_parser->getXMLValue(M_PHOROMATIC_RUN_INSTALL_COMMAND, M_PHOROMATIC_RESPONSE_TRUE))) { phoromatic::set_user_context($xml_parser->getXMLValue(M_PHOROMATIC_SET_CONTEXT_PRE_INSTALL), $phoromatic_trigger, $phoromatic_schedule_id, 'INSTALL'); pts_client::set_test_flags($test_flags); pts_test_installer::standard_install($suite_identifier); } phoromatic::set_user_context($xml_parser->getXMLValue(M_PHOROMATIC_SET_CONTEXT_PRE_RUN), $phoromatic_trigger, $phoromatic_schedule_id, 'INSTALL'); // Do the actual running if(pts_test_run_manager::initial_checks($suite_identifier)) { $test_run_manager = new pts_test_run_manager($test_flags); // Load the tests to run if($test_run_manager->load_tests_to_run($suite_identifier)) { if(pts_strings::string_bool($xml_parser->getXMLValue(M_PHOROMATIC_UPLOAD_TO_GLOBAL, 'FALSE'))) { $test_run_manager->auto_upload_to_openbenchmarking(); } // Save results? $test_run_manager->auto_save_results(date('Y-m-d H:i:s'), $phoromatic_results_identifier, 'A Phoromatic run.'); // Run the actual tests $test_run_manager->pre_execution_process(); $test_run_manager->call_test_runs(); $test_run_manager->post_execution_process(); // Upload to Phoromatic pts_file_io::unlink(PTS_TEST_SUITE_PATH . 'local/' . $suite_identifier . '/suite-definition.xml'); // Upload test results if(is_file(PTS_SAVE_RESULTS_PATH . $save_identifier . '/composite.xml')) { phoromatic::update_system_status('Uploading Test Results'); $times_tried = 0; do { if($times_tried > 0) { echo PHP_EOL . 'Connection to server failed. Trying again in 60 seconds...' . PHP_EOL; sleep(60); } $uploaded_test_results = phoromatic::upload_test_results($save_identifier, $phoromatic_schedule_id, $phoromatic_results_identifier, $phoromatic_trigger); $times_tried++; } while($uploaded_test_results == false && $times_tried < 5); if($uploaded_test_results == false) { echo 'Server connection failed. Exiting...' . PHP_EOL; return false; } if(pts_strings::string_bool($xml_parser->getXMLValue(M_PHOROMATIC_ARCHIVE_RESULTS_LOCALLY, M_PHOROMATIC_RESPONSE_TRUE)) == false) { pts_client::remove_saved_result_file($save_identifier); } } } } break; case M_PHOROMATIC_RESPONSE_EXIT: echo PHP_EOL . 'Phoromatic received a remote command to exit.' . PHP_EOL; phoromatic::update_system_status('Exiting Phoromatic'); pts_client::release_lock(PTS_USER_PATH . 'phoromatic_lock'); $exit_loop = true; break; case M_PHOROMATIC_RESPONSE_SERVER_MAINTENANCE: // The Phoromatic server is down for maintenance, so don't bother updating system status and wait longer before checking back echo PHP_EOL . 'The Phoromatic server is currently down for maintenance. Waiting for service to be restored.' . PHP_EOL; sleep((15 - (date('i') % 15)) * 60); break; case M_PHOROMATIC_RESPONSE_SHUTDOWN: echo PHP_EOL . 'Shutting down the system.' . PHP_EOL; $exit_loop = true; shell_exec('poweroff'); // Currently assuming root break; case M_PHOROMATIC_RESPONSE_REBOOT: echo PHP_EOL . 'Rebooting the system.' . PHP_EOL; $exit_loop = true; shell_exec('reboot'); // Currently assuming root break; case M_PHOROMATIC_RESPONSE_IDLE: default: phoromatic::update_system_status('Idling, Waiting For Task'); sleep((10 - (date('i') % 10)) * 60); // Check with server every 10 minutes break; } if(phodevi::system_hardware(true) != $current_hw || phodevi::system_software(true) != $current_sw) { // Hardware and/or software has changed while PTS/Phoromatic has been running, update the Phoromatic Server echo 'Updating Installed Hardware / Software With Phoromatic Server' . PHP_EOL; phoromatic::update_system_details(); $current_hw = phodevi::system_hardware(true); $current_sw = phodevi::system_software(true); } } while($exit_loop == false); phoromatic::update_system_status('Offline'); } // // Process Functions // public static function __pre_test_install($test_identifier) { static $last_update_time = 0; if(time() > ($last_update_time + 600)) { phoromatic::update_system_status('Installing Tests'); $last_update_time = time(); } } public static function __pre_test_run($pts_test_result) { // TODO: need a way to get the estimated time remaining from the test_run_manager so we can pass that back to the update_system_status parameter so server can read it // TODO: report name of test identifier/run i.e. . ' For ' . PHOROMATIC_TITLE phoromatic::update_system_status('Running ' . $pts_test_result->test_profile->get_identifier()); } public static function __event_user_error($user_error) { // Report PTS user error warnings to Phoromatic server phoromatic::report_warning_to_phoromatic($user_error->get_error_string()); } public static function __event_results_saved($test_run_manager) { if(pts_module::read_variable('AUTO_UPLOAD_RESULTS_TO_PHOROMATIC') && pts_module::is_module_setup()) { phoromatic::upload_unscheduled_test_results($test_run_manager->get_file_name()); } } // // Other Functions // protected static function read_xml_value($file, $xml_option) { $xml_parser = new nye_XmlReader($file); return $xml_parser->getXMLValue($xml_option); } private static function set_user_context($context_script, $trigger, $schedule_id, $process) { if(!empty($context_script)) { if(!is_executable($context_script)) { if(($context_script = pts_client::executable_in_path($context_script)) == false || !is_executable($context_script)) { return false; } } $storage_path = pts_module::save_dir() . 'memory.pt2so'; $storage_object = pts_storage_object::recover_from_file($storage_path); // We check to see if the context was already set but the system rebooted or something in that script if($storage_object == false) { $storage_object = new pts_storage_object(true, true); } else if($storage_object->read_object('last_set_context_trigger') == $trigger && $storage_object->read_object('last_set_context_schedule') == $schedule_id && $storage_object->read_object('last_set_context_process') == $process) { // If the script already ran once for this trigger, don't run it again return false; } $storage_object->add_object('last_set_context_trigger', $trigger); $storage_object->add_object('last_set_context_schedule', $schedule_id); $storage_object->add_object('last_set_context_process', $process); $storage_object->save_to_file($storage_path); // Run the set context script exec($context_script . ' ' . $trigger); // Just simply return true for now, perhaps check exit code status and do something return true; } return false; } protected static function update_system_details() { $server_response = phoromatic::upload_to_remote_server(array('r' => 'update_system_details', 'h' => phodevi::system_hardware(true), 's' => phodevi::system_software(true))); self::$phoromatic_server_build = self::read_xml_value($server_response, M_PHOROMATIC_SERVER_BUILD); return self::read_xml_value($server_response, M_PHOROMATIC_GEN_RESPONSE) == M_PHOROMATIC_RESPONSE_TRUE; } protected static function update_system_status($current_task, $estimated_time_remaining = 0) { $server_response = phoromatic::upload_to_remote_server(array('r' => 'update_system_status', 'a' => $current_task, 'time' => $estimated_time_remaining)); return self::read_xml_value($server_response, M_PHOROMATIC_GEN_RESPONSE) == M_PHOROMATIC_RESPONSE_TRUE; } protected static function report_warning_to_phoromatic($warning) { $server_response = phoromatic::upload_to_remote_server(array('r' => 'report_pts_warning', 'a' => $warning)); return self::read_xml_value($server_response, M_PHOROMATIC_GEN_RESPONSE) == M_PHOROMATIC_RESPONSE_TRUE; } private static function capture_test_logs($save_identifier) { $data = array('system-logs' => null, 'test-logs' => null); if(is_dir(PTS_SAVE_RESULTS_PATH . $save_identifier . '/system-logs/')) { $system_logs_zip = pts_client::create_temporary_file(); pts_compression::zip_archive_create($system_logs_zip, PTS_SAVE_RESULTS_PATH . $save_identifier . '/system-logs/'); $data['system-logs'] = base64_encode(file_get_contents($system_logs_zip)); unlink($system_logs_zip); } if(is_dir(PTS_SAVE_RESULTS_PATH . $save_identifier . '/test-logs/')) { $test_logs_zip = pts_client::create_temporary_file(); pts_compression::zip_archive_create($test_logs_zip, PTS_SAVE_RESULTS_PATH . $save_identifier . '/test-logs/'); $data['test-logs'] = base64_encode(file_get_contents($test_logs_zip)); unlink($test_logs_zip); } return $data; } protected static function upload_test_results($save_identifier, $phoromatic_schedule_id, $results_identifier, $phoromatic_trigger) { $composite_xml = file_get_contents(PTS_SAVE_RESULTS_PATH . $save_identifier . '/composite.xml'); $logs = self::capture_test_logs($save_identifier); $server_response = phoromatic::upload_to_remote_server(array( 'r' => 'upload_test_results', 'c' => $composite_xml, 'i' => $phoromatic_schedule_id, 'ti' => $results_identifier, 'ts' => $phoromatic_trigger, 'sl' => $logs['system-logs'], 'tl' => $logs['test-logs'] )); return self::read_xml_value($server_response, M_PHOROMATIC_GEN_RESPONSE) == M_PHOROMATIC_RESPONSE_TRUE; } protected static function upload_unscheduled_test_results($save_identifier) { $composite_xml = file_get_contents(PTS_SAVE_RESULTS_PATH . $save_identifier . '/composite.xml'); $logs = self::capture_test_logs($save_identifier); $server_response = phoromatic::upload_to_remote_server(array( 'r' => 'upload_test_results_unscheduled', 'c' => $composite_xml, 'i' => 0, 'ti' => 'Unknown', 'sl' => $logs['system-logs'], 'tl' => $logs['test-logs'] )); $xml_parser = new nye_XmlReader($server_response); switch($xml_parser->getXMLValue(M_PHOROMATIC_GEN_RESPONSE)) { case M_PHOROMATIC_RESPONSE_TRUE: echo PHP_EOL . 'Uploaded To Phoromatic.' . PHP_EOL; break; case M_PHOROMATIC_RESPONSE_ERROR: echo PHP_EOL . 'An Error Occurred.' . PHP_EOL; break; case M_PHOROMATIC_RESPONSE_SETTING_DISABLED: echo PHP_EOL . 'You need to enable this support from your Phoromatic account web interface.' . PHP_EOL; break; } return $xml_parser->getXMLValue(M_PHOROMATIC_GEN_RESPONSE) == M_PHOROMATIC_RESPONSE_TRUE; } protected static function phoromatic_setup_module() { if(!pts_module::is_module_setup()) { echo PHP_EOL . 'You first must run:' . PHP_EOL . PHP_EOL . 'phoronix-test-suite module-setup phoromatic' . PHP_EOL . PHP_EOL; return false; } self::$phoromatic_host = pts_module::read_option('remote_host'); self::$phoromatic_account = pts_module::read_option('remote_account'); self::$phoromatic_verifier = pts_module::read_option('remote_verifier'); self::$phoromatic_system = pts_module::read_option('remote_system'); if(extension_loaded('openssl') == false) { // OpenSSL is not supported therefore no HTTPS support self::$phoromatic_host = str_replace('https://', 'http://', self::$phoromatic_host); } $phoromatic = 'phoromatic'; pts_module_manager::attach_module($phoromatic); return true; } protected static function phoromatic_schedule_entry_string($title, $description, $start_time, $active_on) { echo PHP_EOL . $title . ':' . PHP_EOL; echo "\t" . $description . PHP_EOL; echo "\t" . 'Runs at ' . $start_time . ' on ' . pts_strings::parse_week_string($active_on) . '.' . PHP_EOL; } // // Connection // protected static function make_server_request($to_post = array()) // previously was upload_to_remote_server() { static $last_communication_minute = null; static $communication_attempts = 0; if($last_communication_minute == date('i') && $communication_attempts > 3) { // Something is wrong, Phoromatic shouldn't be communicating with server more than four times a minute return false; } else { if(date('i') != $last_communication_minute) { $last_communication_minute = date('i'); $communication_attempts = 0; } $communication_attempts++; } return pts_openbenchmarking::make_openbenchmarking_request('ekofisk', $to_post); } } ?> phoronix-test-suite/pts-core/modules/update_checker.php0000644000175000017500000000424511606671442023515 0ustar michaelmichael. */ class update_checker extends pts_module_interface { const module_name = 'Update Checker'; const module_version = '0.2.0'; const module_description = 'This module checks to see if the Phoronix Test Suite -- and its tests and suites -- are up to date.'; const module_author = 'Phoronix Media'; public static function __pre_option_process() { // Once a day check for new version if(IS_FIRST_RUN_TODAY) { // Check For pts-core updates $latest_reported_version = pts_network::http_get_contents('http://www.phoronix-test-suite.com/LATEST'); $current_e = explode('.', PTS_VERSION); $latest_e = explode('.', $latest_reported_version); if($latest_reported_version != PTS_VERSION && $latest_e[0] >= $current_e[0] && ($latest_e[1] > $current_e[1] || ($latest_e[1] == $current_e[1] && $latest_e[2] >= $current_e[2]))) { // New version of PTS is available pts_client::$display->generic_heading('An outdated version of the Phoronix Test Suite is installed.' . PHP_EOL . 'The version in use is v' . PTS_VERSION . ', but the latest is v' . $latest_reported_version . '.' . PHP_EOL . 'Visit http://www.phoronix-test-suite.com/ to update this software.'); } } return pts_module::MODULE_UNLOAD; // This module doesn't have anything else to do } } ?> phoronix-test-suite/pts-core/modules/result_notifier.php0000644000175000017500000001527211564533734023772 0ustar michaelmichael. SETUP STEPS: 1.) Run 'phoronix-test-suite module-setup result_notifier' 2.) This will prompt you through inputting the commands / absolute file paths to executables to run for each step. Leave empty for irrelevant ones. 3.) To have this module always load automatically by the phoronix-test-suite command, add result_notifier to the LoadModules tag in ~/.phoronix-test-suite/user-config.xml i.e. my config portion looked like: toggle_screensaver, update_checker, result_notifier 4.) Should be all set for testing... My initial tests (just using some scripts that wrote some temporary files of the different exported env variables all worked fine. */ class result_notifier extends pts_module_interface { const module_name = 'Result Notifier'; const module_version = '1.1.0'; const module_description = 'A notification module.'; const module_author = 'Michael Larabel'; public static function module_info() { return null; } public static function module_setup() { return array( new pts_module_option('pre_test_process', 'Pre-test process hook', null), new pts_module_option('pre_test_run_process', 'Pre-test run execution hook', null), new pts_module_option('interim_test_run_process', 'Interim-test run execution hook', null), new pts_module_option('post_test_run_process', 'Post-test run execution hook', null), new pts_module_option('post_test_process', 'Post-test process script', null) ); } public static function __startup() { // NOTE: This will just print to the terminal when PTS has loaded this module, so you know in fact it's being loaded/should be working echo PHP_EOL . 'The result_notifier module for providing external hooks has been loaded.' . PHP_EOL; } public static function __pre_run_process(&$object) { $executable = pts_module::read_option('pre_test_process'); self::process_user_config_external_hook_process('pre_test_process', $executable, 'Running the pre-test process external hook', $object); } public static function __pre_test_run(&$object) { $executable = pts_module::read_option('pre_test_run_process'); self::process_user_config_external_hook_process('pre_test_run_process', $executable, 'Running the pre-test external hook', $object); } public static function __interim_test_run(&$object) { $executable = pts_module::read_option('interim_test_run_process'); self::process_user_config_external_hook_process('interim_test_run_process', $executable, 'Running the interim-test external hook', $object); } public static function __post_test_run(&$object) { $executable = pts_module::read_option('post_test_run_process'); self::process_user_config_external_hook_process('post_test_run_process', $executable, 'Running the post-test external hook', $object); } public static function __post_run_process(&$object) { $executable = pts_module::read_option('post_test_process'); self::process_user_config_external_hook_process('post_test_process', $executable, 'Running the post-test process external hook', $object); } // This is called after the XML save, but not sure Intel needs this since __post_run_process is there too... /* public static function __post_test_run_process(&$object) { $executable = pts_module::read_option('post_test_process'); self::process_user_config_external_hook_process($executable, 'Doing external post test process', $object); } */ 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; } } ?> phoronix-test-suite/pts-core/modules/graphics_override.php0000644000175000017500000001407311620747374024252 0ustar michaelmichael. */ class graphics_override extends pts_module_interface { const module_name = "Graphics Override"; const module_version = "1.0.5"; const module_description = "This module allows you to override some graphics rendering settings for the ATI and NVIDIA drivers while running the Phoronix Test Suite."; const module_author = "Michael Larabel"; public static $module_store_vars = array("FORCE_AA", "FORCE_AF"); static $preset_aa = FALSE; static $preset_af = FALSE; static $preset_aa_control = FALSE; static $preset_af_control = FALSE; static $supported_aa_levels = array(0, 2, 4, 8, 16); static $supported_af_levels = array(0, 2, 4, 8, 16); public static function module_environmental_variables() { return array('FORCE_AA', 'FORCE_AF'); } public static function set_nvidia_extension($attribute, $value) { // Sets an object in NVIDIA's NV Extension if(phodevi::is_nvidia_graphics()) { shell_exec("nvidia-settings --assign " . $attribute . "=" . $value . " 2>&1"); } } public static function set_amd_pcsdb($attribute, $value) { // Sets a value for AMD's PCSDB, Persistent Configuration Store Database if(phodevi::is_ati_graphics() && phodevi::is_linux() && !empty($value)) { $DISPLAY = substr(pts_client::read_env("DISPLAY"), 1, 1); $info = shell_exec("DISPLAY=:" . $DISPLAY . " aticonfig --set-pcs-val=" . $attribute . "," . $value . " 2>&1"); } } public static function __pre_run_process() { if(!(phodevi::is_nvidia_graphics() || (phodevi::is_ati_graphics() && phodevi::is_linux()))) { echo "\nNo supported driver found for graphics_override module!\n"; return pts_module::MODULE_UNLOAD; // Not using a supported driver, quit the module } $force_aa = pts_module::read_variable("FORCE_AA"); $force_af = pts_module::read_variable("FORCE_AF"); if($force_aa !== FALSE && in_array($force_aa, self::$supported_aa_levels)) { // First backup any existing override, then set the new value if(phodevi::is_nvidia_graphics()) { self::$preset_aa = phodevi_parser::read_nvidia_extension("FSAA"); self::$preset_aa_control = phodevi_parser::read_nvidia_extension("FSAAAppControlled"); switch($force_aa) { case 2: $nvidia_aa = 2; break; case 4: $nvidia_aa = 5; break; case 8: $nvidia_aa = 7; break; case 16: $nvidia_aa = 8; break; } if(isset($nvidia_aa)) { self::set_nvidia_extension("FSAA", $nvidia_aa); self::set_nvidia_extension("FSAAAppControlled", 0); } } else if(phodevi::is_ati_graphics()) { self::$preset_aa = phodevi_linux_parser::read_amd_pcsdb("OpenGL,AntiAliasSamples"); self::$preset_aa_control = phodevi_linux_parser::read_amd_pcsdb("OpenGL,AAF"); switch($force_aa) { case 2: $ati_aa = "0x00000002"; break; case 4: $ati_aa = "0x00000004"; break; case 8: $ati_aa = "0x00000008"; break; case 16: echo "\nThe ATI fglrx driver currently does not support 16x AA! Defaulting to 8x AA!\n"; $ati_aa = "0x00000008"; break; } if(isset($ati_aa)) { self::set_amd_pcsdb("OpenGL,AntiAliasSamples", $ati_aa); self::set_amd_pcsdb("OpenGL,AAF", "0x00000000"); } } } if($force_af !== FALSE && in_array($force_af, self::$supported_af_levels)) { // First backup any existing override, then set the new value if(phodevi::is_nvidia_graphics()) { self::$preset_af = phodevi_parser::read_nvidia_extension("LogAniso"); self::$preset_af_control = phodevi_parser::read_nvidia_extension("LogAnisoAppControlled"); switch($force_af) { case 2: $nvidia_af = 1; break; case 4: $nvidia_af = 2; break; case 8: $nvidia_af = 3; break; case 16: $nvidia_af = 4; break; } if(isset($nvidia_af)) { self::set_nvidia_extension("LogAniso", $nvidia_af); self::set_nvidia_extension("LogAnisoAppControlled", 0); } } else if(phodevi::is_ati_graphics()) { self::$preset_af = phodevi_linux_parser::read_amd_pcsdb("OpenGL,AnisoDegree"); switch($force_af) { case 2: $ati_af = "0x00000002"; break; case 4: $ati_af = "0x00000004"; break; case 8: $ati_af = "0x00000008"; break; case 16: $ati_af = "0x00000010"; break; } if(isset($ati_af)) { self::set_amd_pcsdb("OpenGL,AnisoDegree", $ati_af); } } } } public static function __post_option_process() { if(phodevi::is_nvidia_graphics()) { if(self::$preset_aa !== FALSE) { self::set_nvidia_extension("FSAA", self::$preset_aa); self::set_nvidia_extension("FSAAAppControlled", self::$preset_aa_control); } if(self::$preset_af !== FALSE) { self::set_nvidia_extension("LogAniso", self::$preset_af); self::set_nvidia_extension("LogAnisoAppControlled", self::$preset_af_control); } } else if(phodevi::is_ati_graphics()) { if(self::$preset_aa !== FALSE) { self::set_amd_pcsdb("OpenGL,AntiAliasSamples", self::$preset_aa); self::set_amd_pcsdb("OpenGL,AAF", self::$preset_aa_control); } if(self::$preset_af !== FALSE) { self::set_amd_pcsdb("OpenGL,AnisoDegree", self::$preset_af); } } } } ?> phoronix-test-suite/pts-core/modules/dummy_module.php0000644000175000017500000001002611564533734023245 0ustar michaelmichael. */ class dummy_module extends pts_module_interface { const module_name = 'Dummy Module'; const module_version = '1.1.0'; const module_description = 'This is a simple module intended for developers to just demonstrate some of the module functions.'; const module_author = 'Phoronix Media'; public static function module_info() { return 'This is a simple module intended for developers to just demonstrate some of the module functions.'; } public static function user_commands() { return array('dummy_command' => 'sample_command'); } // // User Commands // public static function sample_command() { echo PHP_EOL . 'This is a sample function running from a module!' . PHP_EOL; } // // General Functions // public static function __startup() { echo PHP_EOL . 'The Phoronix Test Suite is starting up!' . PHP_EOL . 'Called: __startup()' . PHP_EOL; } public static function __shutdown() { echo PHP_EOL . 'The Phoronix Test Suite is done running.' . PHP_EOL . 'Called: __shutdown()' . PHP_EOL; } // // Installation Functions // public static function __pre_install_process() { echo PHP_EOL . 'Getting ready to check for test(s) that need installing...' . PHP_EOL . 'Called: __pre_install_process()' . PHP_EOL; } public static function __pre_test_download() { echo PHP_EOL . 'Getting ready to download files for a test!' . PHP_EOL . 'Called: __pre_test_download()' . PHP_EOL; } public static function __interim_test_download() { echo PHP_EOL . 'Just finished downloading a file for a test.' . PHP_EOL . 'Called: __interim_test_download()' . PHP_EOL; } public static function __post_test_download() { echo PHP_EOL . 'Just finished the download process for a test.' . PHP_EOL . 'Called: __post_test_download()' . PHP_EOL; } public static function __pre_test_install() { echo PHP_EOL . 'Getting ready to actually install a test!' . PHP_EOL . 'Called: __pre_test_install()' . PHP_EOL; } public static function __post_test_install() { echo PHP_EOL . 'Just finished installing a test, is there anything to do?' . PHP_EOL . 'Called: __post_test_install()' . PHP_EOL; } public static function __post_install_process() { echo PHP_EOL . 'We\'re all done installing any needed tests. Anything to process?' . PHP_EOL . 'Called: __post_install_process()' . PHP_EOL; } // // Run Functions // public static function __pre_run_process() { echo PHP_EOL . 'We\'re about to start the actual testing process.' . PHP_EOL . 'Called: __pre_run_process()' . PHP_EOL; } public static function __pre_test_run() { echo PHP_EOL . 'We\'re about to run a test! Any pre-run processing?' . PHP_EOL . 'Called: __pre_test_run()' . PHP_EOL; } public static function __interim_test_run() { echo PHP_EOL . 'This test is being run multiple times for accuracy. Anything to do between tests?' . PHP_EOL . 'Called: __interim_test_run()' . PHP_EOL; } public static function __post_test_run() { echo PHP_EOL . 'We\'re all done running this specific test.' . PHP_EOL . 'Called: __post_test_run()' . PHP_EOL; } public static function __post_run_process() { echo PHP_EOL . 'We\'re all done with the testing for now.' . PHP_EOL . 'Called: __post_run_process()' . PHP_EOL; } } ?> phoronix-test-suite/pts-core/modules/matisk.php0000644000175000017500000004274311676644707022057 0ustar michaelmichael. */ class matisk extends pts_module_interface { const module_name = 'MATISK'; const module_version = '1.1.0'; const module_description = 'My Automated Test Infrastructure Setup Kit'; const module_author = 'Michael Larabel'; // For values array template [0] = default value [1] = description private static $ini_struct = array( 'workload' => array( 'save_results' => array(true, 'A boolean value of whether to save the test results.'), 'suite' => array(null, 'A string that is an XML test suite for the Phoronix Test Suite. If running a custom collection of tests/suites, first run phoronix-test-suite build-suite.'), 'save_name' => array(null, 'The string to save the test results as.'), 'description' => array(null, 'The test description string.'), 'result_identifier' => array(null, 'The test result identifier string, unless using contexts.') ), 'installation' => array( 'install_check' => array(true, 'Check to see that all tests/suites are installed prior to execution.'), 'force_install' => array(false, 'Force all tests/suites to be re-installed each time prior to execution.'), 'external_download_cache' => array(null, 'The option to specify a non-standard PTS External Dependencies download cache directory.'), 'block_phodevi_caching' => array(false, 'If Phodevi should not be caching any hardware/software information.') ), 'general' => array( 'upload_to_openbenchmarking' => array(false, 'A boolean value whether to automatically upload the test result to OpenBenchmarking.org'), // Automatic upload to OpenBenchmarking? // 'open_browser' => false, // Automatically launch web browser to show the results? ), 'environmental_variables' => array( 'EXAMPLE_VAR' => array('EXAMPLE', 'The environmental_variables section allows key = value pairs of environmental variables to be set by default.') ), 'set_context' => array( 'The pre_install or pre_run fields must be used when using the MATISK context testing functionality. The set_context fields must specify an executable file for setting the context of the system. Passed as the first argument to the respective file is the context string defined by the contexts section of this file. If any of the set_context scripts emit an exit code of 8, the testing process will abort immediately. If any of the set_context scripts emit an exit code of 9, the testing process will skip executing the suite on the current context.', 'pre_install' => array(null, 'An external file to be used for setting the system context prior to test installation.'), 'pre_run' => array(null, 'An external file to be used for setting the system context prior to test execution.'), // 'interim_run' => array(null, 'An external file to be used for setting the system context in between tests in the execution queue.'), 'post_install' => array(null, 'An external file to be used for setting the system context after the test installation.'), 'post_run' => array(null, 'An external file to be used for setting the system context after all tests have been executed.'), 'reboot_support' => array(false, 'If any of the context scripts cause the system to reboot, set this value to true and the Phoronix Test Suite will attempt to automatically recover itself upon reboot.'), 'context' => array(array(), 'An array of context values.'), 'external_contexts' => array(null, 'An external file for loading a list of contexts, if not loading the list of contexts via the context array in this file. If the external file is a script it will be executed and the standard output will be used for parsing the contexts.'), 'external_contexts_delimiter' => array('EOL', 'The delimiter for the external_contexts contexts list. Special keyword: EOL will use a line break as the delimiter and TAB will use a tab as a delimiter.'), 'reverse_context_order' => array(false, 'A boolean value of whether to reverse the order (from bottom to top) for the execution of a list of contexts.'), 'log_context_outputs' => array(false, 'A boolean value of whether to log the output of the set-context scripts to ~/.phoronix-test-suite/modules-data/matisk/') ) ); private static $context = null; private static $ini = array(); private static $matisk_config_dir = null; private static $skip_test_set = false; public static function module_info() { return null; } public static function user_commands() { return array('run' => 'run_matisk', 'template' => 'template'); } public static function template() { echo PHP_EOL . '; Sample INI Configuration Template For Phoronix Test Suite MATISK' . PHP_EOL . '; http://www.phoronix-test-suite.com/' . PHP_EOL . PHP_EOL; foreach(self::$ini_struct as $section => $items) { echo PHP_EOL . '[' . $section . ']' . PHP_EOL; foreach($items as $key => $r) { if(!is_array($r)) { echo PHP_EOL . '; ' . wordwrap($r, 80, PHP_EOL . '; ', true) . PHP_EOL . PHP_EOL; continue; } list($default_value, $description) = $r; if($description != null) { echo '; ' . wordwrap($description, 80, PHP_EOL . '; ', true); if($default_value !== null && $default_value != array()) { echo ' The default value is '; if($default_value === true || $default_value === false) { echo $default_value === true ? 'TRUE' : 'FALSE'; } else { echo $default_value; } echo '.'; } echo PHP_EOL; } if(is_array($default_value)) { $default_value = isset($default_value[0]) ? $default_value[0] : null; echo $key . '[] = ' . $default_value . PHP_EOL; echo $key . '[] = ' . $default_value; } else { echo $key . ' = '; if($default_value === true || $default_value === false) { echo $default_value === true ? 'TRUE' : 'FALSE'; } else { echo $default_value; } } echo PHP_EOL . PHP_EOL; } } } private static function find_file($file) { if(is_file($file)) { $file = $file; } else if(is_file(self::$matisk_config_dir . $file)) { $file = self::$matisk_config_dir . $file; } else { $file = false; } return $file; } public static function run_matisk($args) { echo PHP_EOL . 'MATISK For The Phoronix Test Suite' . PHP_EOL; if(!isset($args[0]) || !is_file($args[0])) { echo PHP_EOL . 'You must specify a MATISK INI file to load.' . PHP_EOL . PHP_EOL; return false; } self::$matisk_config_dir = dirname($args[0]) . '/'; pts_file_io::mkdir(pts_module::save_dir()); $ini = parse_ini_file($args[0], true); foreach(self::$ini_struct as $section => $items) { foreach($items as $key => $r) { if(is_array($r) && !isset($ini[$section][$key])) { $ini[$section][$key] = $r[0]; } } } // Checks if(pts_test_suite::is_suite($ini['workload']['suite']) == false) { // See if the XML suite-definition was just tossed into the same directory if(($xml_file = self::find_file($ini['workload']['suite'] . '.xml')) !== false) { pts_file_io::mkdir(PTS_TEST_SUITE_PATH . 'local/' . $ini['workload']['suite']); copy($xml_file, PTS_TEST_SUITE_PATH . 'local/' . $ini['workload']['suite'] . '/suite-definition.xml'); } if(pts_test_suite::is_suite($ini['workload']['suite']) == false) { echo PHP_EOL . 'A test suite must be specified to execute. If a suite needs to be constructed, run: ' . PHP_EOL . 'phoronix-test-suite build-suite' . PHP_EOL . PHP_EOL; return false; } } if($ini['set_context']['external_contexts'] != null) { switch($ini['set_context']['external_contexts_delimiter']) { case 'EOL': case '': $ini['set_context']['external_contexts_delimiter'] = PHP_EOL; break; case 'TAB': $ini['set_context']['external_contexts_delimiter'] = "\t"; break; } if(($ff = self::find_file($ini['set_context']['external_contexts']))) { if(is_executable($ff)) { $ini['set_context']['context'] = shell_exec($ff . ' 2> /dev/null'); } else { $ini['set_context']['context'] = file_get_contents($ff); } } else { // Hopefully it's a command to execute then... $ini['set_context']['context'] = shell_exec($ini['set_context']['external_contexts'] . ' 2> /dev/null'); } $ini['set_context']['context'] = explode($ini['set_context']['external_contexts_delimiter'], $ini['set_context']['context']); } else if($ini['set_context']['context'] != null && !is_array($ini['set_context']['context'])) { $ini['set_context']['context'] = array($ini['set_context']['context']); } if(is_array($ini['set_context']['context']) && count($ini['set_context']['context']) > 0) { foreach($ini['set_context']['context'] as $i => $context) { if($context == null) { unset($ini['set_context']['context'][$i]); } } // Context testing if(count($ini['set_context']['context']) > 0 && $ini['set_context']['pre_run'] == null && $ini['set_context']['pre_install'] == null) { echo PHP_EOL . 'The pre_run or pre_install set_context fields must be set in order to set the system\'s context.' . PHP_EOL; return false; } if($ini['set_context']['reverse_context_order']) { $ini['set_context']['context'] = array_reverse($ini['set_context']['context']); } } if(pts_strings::string_bool($ini['workload']['save_results'])) { if($ini['workload']['save_name'] == null) { echo PHP_EOL . 'The save_name field cannot be left empty when saving the test results.' . PHP_EOL; return false; } /* if($ini['workload']['result_identifier'] == null) { echo PHP_EOL . 'The result_identifier field cannot be left empty when saving the test results.' . PHP_EOL; return false; } */ } if(!empty($ini['environmental_variables']) && is_array($ini['environmental_variables'])) { foreach($ini['environmental_variables'] as $key => $value) { putenv(trim($key) . '=' . trim($value)); } } if(empty($ini['set_context']['context'])) { $ini['set_context']['context'] = array($ini['workload']['result_identifier']); } if(pts_strings::string_bool($ini['set_context']['log_context_outputs'])) { pts_file_io::mkdir(pts_module::save_dir() . $ini['workload']['save_name']); } $spent_context_file = pts_module::save_dir() . $ini['workload']['save_name'] . '.spent-contexts'; if(!is_file($spent_context_file)) { touch($spent_context_file); } else { // If recovering from an existing run, don't rerun contexts that were already executed $spent_contexts = pts_file_io::file_get_contents($spent_context_file); $spent_contexts = explode(PHP_EOL, $spent_contexts); foreach($spent_contexts as $sc) { if(($key = array_search($sc, $ini['set_context']['context'])) !== false) { unset($ini['set_context']['context'][$key]); } } } if($ini['set_context']['reboot_support'] && phodevi::is_linux()) { // In case a set-context involves a reboot, auto-recover $xdg_config_home = is_dir('/etc/xdg/autostart') && is_writable('/etc/xdg/autostart') ? '/etc/xdg/autostart' : pts_client::read_env('XDG_CONFIG_HOME'); if($xdg_config_home == false) { $xdg_config_home = pts_client::user_home_directory() . '.config'; } if($xdg_config_home != false && is_dir($xdg_config_home)) { $autostart_dir = $xdg_config_home . '/autostart/'; pts_file_io::mkdir($xdg_config_home . '/autostart/'); } file_put_contents($xdg_config_home . '/autostart/phoronix-test-suite-matisk.desktop', ' [Desktop Entry] Name=Phoronix Test Suite Matisk Recovery GenericName=Phoronix Test Suite Comment=Matisk Auto-Recovery Support Exec=gnome-terminal -e \'phoronix-test-suite matisk ' . $args[0] . '\' Icon=phoronix-test-suite Type=Application Encoding=UTF-8 Categories=System;Monitor;'); } if($ini['installation']['block_phodevi_caching']) { // Block Phodevi caching if changing out system components and there is a chance one of the strings of changed contexts might be cached (e.g. OpenGL user-space driver) phodevi::$allow_phodevi_caching = false; } if(phodevi::system_uptime() < 60) { echo PHP_EOL . 'Sleeping 45 seconds while waiting for the system to settle...' . PHP_EOL; sleep(45); } self::$ini = $ini; $total_context_count = count(self::$ini['set_context']['context']); while(($context = array_shift(self::$ini['set_context']['context'])) !== null) { echo PHP_EOL . ($total_context_count - count(self::$ini['set_context']['context'])) . ' of ' . $total_context_count . ' in test execution queue [' . $context . ']' . PHP_EOL . PHP_EOL; self::$context = $context; if(pts_strings::string_bool(self::$ini['installation']['install_check']) || $ini['set_context']['pre_install'] != null) { self::process_user_config_external_hook_process('pre_install'); $install_flags = pts_c::auto_mode; if(pts_strings::string_bool(self::$ini['installation']['force_install'])) { $install_flags |= pts_c::force_install; } if(self::$ini['installation']['external_download_cache'] != null) { pts_test_install_manager::add_external_download_cache(self::$ini['installation']['external_download_cache']); } // Do the actual test installation pts_test_installer::standard_install(self::$ini['workload']['suite'], $install_flags); self::process_user_config_external_hook_process('post_install'); } $test_flags = pts_c::auto_mode; if(pts_test_run_manager::initial_checks(self::$ini['workload']['suite'], $test_flags) == false) { return false; } if(self::$skip_test_set == false) { self::process_user_config_external_hook_process('pre_run'); $test_run_manager = new pts_test_run_manager($test_flags); // Load the tests to run if($test_run_manager->load_tests_to_run(self::$ini['workload']['suite']) == false) { return false; } // Save results? $result_identifier = $ini['workload']['result_identifier']; if($result_identifier == null) { $result_identifier = '$MATISK_CONTEXT'; } // Allow $MATIISK_CONTEXT as a valid user variable to pass it... $result_identifier = str_replace('$MATISK_CONTEXT', self::$context, $result_identifier); $test_run_manager->set_save_name(self::$ini['workload']['save_name']); $test_run_manager->set_results_identifier($result_identifier); $test_run_manager->set_description(self::$ini['workload']['description']); // Don't upload results unless it's the last in queue where the context count is now 0 $test_run_manager->auto_upload_to_openbenchmarking((count(self::$ini['set_context']['context']) == 0 && self::$ini['general']['upload_to_openbenchmarking'])); // Run the actual tests $test_run_manager->pre_execution_process(); $test_run_manager->call_test_runs(); $test_run_manager->post_execution_process(); } self::$skip_test_set = false; file_put_contents($spent_context_file, self::$context . PHP_EOL, FILE_APPEND); pts_file_io::unlink(pts_module::save_dir() . self::$context . '.last-call'); self::process_user_config_external_hook_process('post_run'); } unlink($spent_context_file); isset($xdg_config_home) && pts_file_io::unlink($xdg_config_home . '/autostart/phoronix-test-suite-matisk.desktop'); } protected static function process_user_config_external_hook_process($process) { // Check to not run the same process $last_call_file = pts_module::save_dir() . self::$context . '.last-call'; if(is_file($last_call_file)) { $check = pts_file_io::file_get_contents($last_call_file); if($process == $check) { unlink($last_call_file); return false; } } $process != 'post_run' && file_put_contents($last_call_file, $process); if(self::$ini['set_context'][$process]) { $command = self::find_file(self::$ini['set_context'][$process]) ? self::find_file(self::$ini['set_context'][$process]) : self::$ini['set_context'][$process]; $descriptor_spec = array( 0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w') ); $env_vars = null; pts_client::$display->test_run_instance_error('Running ' . $process . ' set-context script.'); if(is_executable($command)) { // Pass the context as the first argument to the string $command .= ' ' . self::$context; } else { // Else find $MATISK_CONTEXT in the command string $command = str_replace('$MATISK_CONTEXT', self::$context, $command); } $proc = proc_open($command, $descriptor_spec, $pipes, null, $env_vars); echo $std_output = stream_get_contents($pipes[1]); $return_value = proc_close($proc); if(pts_strings::string_bool(self::$ini['set_context']['log_context_outputs'])) { file_put_contents(pts_module::save_dir() . $ini['workload']['save_name'] . '/' . self::$context . '-' . $process . '.txt', $std_output); } switch($return_value) { case 8: exit(0); case 9: self::$skip_test_set = true; break; } } } } ?> phoronix-test-suite/pts-core/modules/graphics_event_checker.php0000644000175000017500000001420611732736144025233 0ustar michaelmichael. */ class graphics_event_checker extends pts_module_interface { const module_name = 'Graphics Event Checker'; const module_version = '1.0.0'; const module_description = 'This module checks a number of events prior to and and after running a test to make sure the graphics sub-system was not put in a sour or unintended state by the application. For instance, it makes sure syncing to vBlank is not forced through the driver and that a graphics test has not left the display in an unintended mode.'; const module_author = 'Michael Larabel'; static $start_video_resolution = array(-1, -1); static $driver_forced_vsync = false; // GPU Errors static $error_pointer = 0; static $error_count = 0; // Number of GPU errors that were detected static $error_analysis = array(); // Array of error break down. For each array index is for a test where an error happened, it's TEST_NAME => ERROR_COUNT public static function __startup() { /* // Right now Phodevi is just using xrandr to set display modes, so if that's not present, this module will be useless if(!pts_client::executable_in_path('xrandr')) { return pts_module::MODULE_UNLOAD; } */ if(count(phodevi_parser::read_xdpy_monitor_info()) > 1) { // No multi-monitor support right now return pts_module::MODULE_UNLOAD; } } public static function __pre_run_process() { self::$error_count = 0; self::$error_pointer = 0; self::$error_analysis = array(); // Store the video resolution // Access the xrandr resolution directly to ensure it's not polling the FB size or one of the KMS modes self::$start_video_resolution = phodevi_gpu::gpu_xrandr_resolution(); if(phodevi::is_linux() && phodevi::is_ati_graphics()) { $vsync_val = phodevi_linux_parser::read_amd_pcsdb('AMDPCSROOT/SYSTEM/BUSID-*/OpenGL,VSyncControl'); // Check for vSync if($vsync_val == '0x00000002' || $vsync_val == '0x00000003') { self::$driver_forced_vsync = true; } //$catalyst_ai_val = phodevi_linux_parser::read_amd_pcsdb('AMDPCSROOT/SYSTEM/BUSID-*/OpenGL,CatalystAI'); // Check for Catalyst AI //if($catalyst_ai_val == '0x00000001' || $catalyst_ai_val == '0x00000002') // echo '\nCatalyst AI is enabled, which will use driver-specific optimizations in some tests that may offer extra performance enhancements.\n'; } else if(phodevi::is_nvidia_graphics()) { self::$error_pointer = self::nvidia_gpu_error_count(); // Set the error pointer if(phodevi_parser::read_nvidia_extension('SyncToVBlank') == '1') { shell_exec('nvidia-settings -a SyncToVBlank=0 2>&1'); self::$driver_forced_vsync = true; } } if(self::$driver_forced_vsync == true) { // echo '\nYour video driver is forcing vertical sync to be enabled. This will limit the system's frame-rate performance potential in any graphical tests!\n'; } // vblank_mode=0 has long been set within pts-core, but put it here too just since there's these other checks here putenv('vblank_mode=0'); } public static function __post_test_run(&$test_result) { if($test_result->test_profile->get_test_hardware_type() != 'Graphics') { return; } // Check for video resolution changes // Access the xrandr resolution directly to ensure it's not polling the FB size or one of the KMS modes $current_res = phodevi_gpu::gpu_xrandr_resolution(); if($current_res != self::$start_video_resolution && self::$start_video_resolution != array(-1, -1)) { $video_width = $current_res[0]; $video_height = $current_res[1]; $reset = self::$start_video_resolution; $reset_width = $reset[0]; $reset_height = $reset[1]; // echo '\nThe video resolution had changed during testing and it was not properly reset! Now resetting to $reset_width x $reset_height from $video_width x $video_height.\n'; phodevi::set_property('gpu', 'screen-resolution', array($reset_width, $reset_height)); // Sleep for three seconds to allow time for display to settle after mode-set sleep(3); } if(phodevi::is_nvidia_graphics()) { $current_error_position = self::nvidia_gpu_error_count(); if($current_error_position > self::$error_pointer && $test_result instanceof pts_test_result) { // GPU Error(s) Happened During The Test $this_test = $test_result->test_profile->get_identifier(); $this_error_count = $current_error_position - self::$error_pointer; if(isset(self::$error_analysis[$this_test])) { $this_error_count += self::$error_analysis[$this_test]; } self::$error_analysis[$this_test] = $this_error_count; // Tally up errors for this test self::$error_count += $this_error_count; // Add to total error count self::$error_pointer = $current_error_position; // Reset the pointer } } } public static function __post_option_process() { if(self::$error_count > 0) { $error_breakdown = PHP_EOL; foreach(self::$error_analysis as $test => $error_count) { $error_breakdown .= PHP_EOL . $test . ': ' . $error_count; } echo PHP_EOL . 'GPU Errors: ' . $error_count . $error_breakdown . PHP_EOL; } if(phodevi::is_nvidia_graphics() && self::$driver_forced_vsync) { shell_exec('nvidia-settings -a SyncToVBlank=1 2>&1'); } } protected static function nvidia_gpu_error_count() { $count = phodevi_parser::read_nvidia_extension('GPUErrors'); return $count == null || !is_numeric($count) ? 0 : $count; } } ?> phoronix-test-suite/pts-core/modules/timed_screenshot.php0000644000175000017500000000717112000020734024064 0ustar michaelmichael. */ class timed_screenshot extends pts_module_interface { const module_name = 'Timed Screenshot'; const module_version = '1.0.0'; const module_description = 'This is a module that will take a screenshot of the system at a pre-defined interval. ImageMagick must be installed onto the system prior to using this module.'; const module_author = 'Michael Larabel'; protected static $screenshots = array(); protected static $screenshot_interval = 10; protected static $existing_screenshots = array(); public static function module_environmental_variables() { return array('SCREENSHOT_INTERVAL'); } public static function __startup() { // Make sure the file is removed to avoid potential problems if it was leftover from earlier run pts_module::remove_file('is_running'); if(pts_client::executable_in_path('import') == false) { echo PHP_EOL . 'ImageMagick must first be installed onto this system!' . PHP_EOL; return pts_module::MODULE_UNLOAD; } if(($interval = pts_module::read_variable('SCREENSHOT_INTERVAL')) > 1 && is_numeric($interval)) { self::$screenshot_interval = $interval; return true; } return pts_module::MODULE_UNLOAD; self::$existing_screenshots = pts_file_io::glob(pts_module::save_dir() . 'screenshot-*.png'); } public static function __shutdown() { if(!empty(self::$screenshots)) { echo PHP_EOL . count(self::$screenshots) . ' screenshots recorded. They are saved in the ' . pts_module::save_dir() . ' directory.' . PHP_EOL; } } public static function __pre_run_process() { self::$screenshots = array(); pts_module::pts_timed_function('take_screenshot', self::$screenshot_interval); } public static function __pre_test_run() { pts_module::save_file('is_running', 'yes'); } public static function __post_test_run() { pts_module::remove_file('is_running'); $screenshots = self::get_screenshots(); foreach($screenshots as $screenshot) { // Compress the PNGs a bit pts_image::compres_png_image($screenshot, 9); } return $screenshots; } public static function take_screenshot($force = false) { if(pts_module::read_file('is_running') == 'yes' || $force) { $ss_file = pts_module::save_dir() . 'screenshot-' . date('ymd-His') . '.png'; shell_exec('import -window root ' . $ss_file); if(is_file($ss_file)) { array_push(self::$screenshots, $ss_file); return $ss_file; } } return false; } public static function get_screenshots() { if(!empty(self::$screenshots)) { return self::$screenshots; } else { // Another thread is going on and thread empty so try to query the file-system for differences $screenshots = pts_file_io::glob(pts_module::save_dir() . 'screenshot-*.png'); return array_diff($screenshots, self::$existing_screenshots); } } } ?> phoronix-test-suite/pts-core/objects/pts_result_file_analyzer.php0000644000175000017500000002623712214123052025626 0ustar michaelmichael. */ class pts_result_file_analyzer { public static function analyze_result_file_intent(&$result_file, &$flagged_results = -1, $return_all_changed_indexes = false) { $identifiers = $result_file->get_system_identifiers(); if(count($identifiers) < 2) { // Not enough tests to be valid for anything return false; } foreach($identifiers as $identifier) { if(pts_strings::string_only_contains($identifier, pts_strings::CHAR_NUMERIC | pts_strings::CHAR_DASH | pts_strings::CHAR_SPACE)) { // All the identifiers are just dates or other junk return false; } } $hw = $result_file->get_system_hardware(); $hw_unique = array_unique($hw); $sw = $result_file->get_system_software(); $sw_unique = array_unique($sw); $desc = false; if(count($hw_unique) == 1 && count($sw_unique) == 1) { // The hardware and software is maintained throughout the testing, so if there's a change in results its something we aren't monitoring // TODO XXX: Not sure this below check is needed anymore... if(true || (count($hw) > 2 && $result_file->get_unique_test_count() != count($hw) && $result_file->get_test_count() != count($hw))) { $desc = array('Unknown', implode(', ', $identifiers)); } } else if(count($sw_unique) == 1) { // The software is being maintained, but the hardware is being flipped out $rows = array(); $data = array(); pts_result_file_analyzer::system_components_to_table($data, $identifiers, $rows, $hw); pts_result_file_analyzer::compact_result_table_data($data, $identifiers, true); $desc = pts_result_file_analyzer::analyze_system_component_changes($data, $rows, array( array('Processor', 'Motherboard', 'Chipset', 'Audio', 'Network'), // Processor comparison array('Processor', 'Motherboard', 'Chipset', 'Network'), // Processor comparison array('Processor', 'Chipset', 'Graphics'), array('Processor', 'Graphics'), array('Processor', 'Chipset'), // Processor comparison - Sandy/Ivy Bridge for Intel will change CPU/chipset reporting when still using same mobo array('Motherboard', 'Chipset'), // Motherboard comparison array('Motherboard', 'Chipset', 'Audio', 'Network'), // Also a potential motherboard comparison array('Graphics', 'Audio'), // GPU comparison ), $return_all_changed_indexes); } else if(count($hw_unique) == 1) { // The hardware is being maintained, but the software is being flipped out $rows = array(); $data = array(); pts_result_file_analyzer::system_components_to_table($data, $identifiers, $rows, $sw); pts_result_file_analyzer::compact_result_table_data($data, $identifiers, true); $desc = pts_result_file_analyzer::analyze_system_component_changes($data, $rows, array( array('Display Driver', 'OpenGL'), array('OpenGL'), array('Display Driver') // Graphics driver comparisons ), $return_all_changed_indexes); } else { // Both software and hardware are being flipped out $rows = array(); $data = array(); pts_result_file_analyzer::system_components_to_table($data, $identifiers, $rows, $hw); pts_result_file_analyzer::system_components_to_table($data, $identifiers, $rows, $sw); pts_result_file_analyzer::compact_result_table_data($data, $identifiers, true); $desc = pts_result_file_analyzer::analyze_system_component_changes($data, $rows, array( array('Memory', 'Graphics', 'Display Driver', 'OpenGL'), array('Graphics', 'Monitor', 'Kernel', 'Display Driver', 'OpenGL'), array('Graphics', 'Monitor', 'Display Driver', 'OpenGL'), array('Graphics', 'Kernel', 'Display Driver', 'OpenGL'), array('Graphics', 'Display Driver', 'OpenGL'), array('Graphics', 'OpenGL'), array('Graphics', 'Kernel'), array('Graphics', 'Display Driver') // All potential graphics comparisons ), $return_all_changed_indexes); } if($desc) { if($flagged_results === -1) { return $desc; } else { $mark_results = self::locate_interesting_results($result_file, $flagged_results); return array($desc[0], $desc[1], $mark_results); } } return false; } public static function locate_interesting_results(&$result_file, &$flagged_results = null) { $result_objects = array(); if(!is_array($flagged_results)) { $flagged_results = array(); $system_id_keys = null; $result_object_index = -1; pts_ResultFileTable::result_file_to_result_table($result_file, $system_id_keys, $result_object_index, $flagged_results); } if(count($flagged_results) > 0) { asort($flagged_results); $flagged_results = array_slice(array_keys($flagged_results), -6); $flag_delta_objects = $result_file->get_result_objects($flagged_results); for($i = 0; $i < count($flagged_results); $i++) { $result_objects[$flagged_results[$i]] = $flag_delta_objects[$i]; unset($flag_delta_objects[$i]); } } return $result_objects; } public static function analyze_system_component_changes($data, $rows, $supported_combos = array(), $return_all_changed_indexes = false) { $max_combo_count = 2; foreach($supported_combos as $combo) { if(($c = count($combo)) > $max_combo_count) { $max_combo_count = $c; } } $total_width = count($data); $first_objects = array_shift($data); $comparison_good = true; $comparison_objects = array(); foreach($first_objects as $i => $o) { if($o->get_attribute('spans_col') == $total_width) { unset($first_objects[$i]); } } if(count($first_objects) <= $max_combo_count && count($first_objects) > 0) { $changed_indexes = array_keys($first_objects); array_push($comparison_objects, ($return_all_changed_indexes ? array_map('strval', $first_objects) : implode('/', $first_objects))); if(count($changed_indexes) <= $max_combo_count) { while($comparison_good && ($this_identifier = array_shift($data)) !== null) { if(empty($this_identifier)) { continue; } $this_keys = array_keys($this_identifier); $do_push = false; if($this_keys != $changed_indexes) { foreach($this_keys as &$change) { $change = $rows[$change]; } if(!in_array($this_keys, $supported_combos) && (count($this_keys) > 1 || array_search($this_keys[0], $supported_combos[0]) === false)) { $comparison_good = false; } else { $do_push = true; } } else { $do_push = true; } if($do_push) { array_push($comparison_objects, ($return_all_changed_indexes ? array_map('strval', $this_identifier) : implode('/', $this_identifier))); } } } else { $comparison_good = false; } if($comparison_good) { $new_index = array(); foreach($changed_indexes as &$change) { $new_index[$change] = $rows[$change]; } $changed_indexes = $new_index; if(count($changed_indexes) == 1 || in_array(array_values($changed_indexes), $supported_combos)) { if($return_all_changed_indexes == false) { $comparison_objects = implode(', ', $comparison_objects); } return array(($return_all_changed_indexes ? $changed_indexes : array_shift($changed_indexes)), $comparison_objects); } } } return false; } public static function system_components_to_table(&$table_data, &$columns, &$rows, $add_components) { $col_pos = 0; foreach($add_components as $info_string) { if(isset($columns[$col_pos])) { if(!isset($table_data[$columns[$col_pos]])) { $table_data[$columns[$col_pos]] = array(); } foreach(explode(', ', $info_string) as $component) { $c_pos = strpos($component, ': '); if($c_pos !== false) { $index = substr($component, 0, $c_pos); $value = substr($component, ($c_pos + 2)); if(($r_i = array_search($index, $rows)) === false) { array_push($rows, $index); $r_i = count($rows) - 1; } $table_data[$columns[$col_pos]][$r_i] = self::system_value_to_ir_value($value, $index); } } } $col_pos++; } } public static function system_component_string_to_array($components, $do_check = false) { $component_r = array(); $components = explode(', ', $components); foreach($components as &$component) { $component = explode(': ', $component); if(count($component) >= 2 && ($do_check == false || in_array($component[0], $do_check))) { $component_r[$component[0]] = $component[1]; } } return $component_r; } public static function system_component_string_to_html($components) { $components = self::system_component_string_to_array($components); foreach($components as $type => &$component) { $component = self::system_value_to_ir_value($component, $type); $type = '' . $type . ''; if(($href = $component->get_attribute('href')) != false) { $component = '' . $component->get_value() . ''; } else { $component = $component->get_value(); } $component = $type . ': ' . $component; } return implode(', ', $components); } public static function system_value_to_ir_value($value, $index) { $ir = new pts_graph_ir_value($value); if(!in_array($index, array('Memory', 'System Memory', 'Desktop', 'Screen Resolution', 'System Layer')) && $value != 'Unknown') { $value = pts_strings::trim_search_query($value); if($value != null) { $ir->set_attribute('href', 'http://openbenchmarking.org/s/' . $value); } } return $ir; } public static function compact_result_table_data(&$table_data, &$columns, $unset_emptied_values = false) { // Let's try to compact the data $c_count = count($table_data); $c_index = 0; foreach(array_keys($table_data) as $c) { foreach(array_keys($table_data[$c]) as $r) { // Find next-to duplicates $match_to = &$table_data[$c][$r]; if(($match_to instanceof pts_graph_ir_value) == false) { if($unset_emptied_values) { unset($table_data[$c][$r]); } continue; } $spans = 1; for($i = ($c_index + 1); $i < $c_count; $i++) { $id = $columns[$i]; if(isset($table_data[$id][$r]) && $match_to == $table_data[$id][$r]) { $spans++; if($unset_emptied_values) { unset($table_data[$id][$r]); } else { $table_data[$id][$r] = null; } } else { break; } } if($spans > 1) { $match_to->set_attribute('spans_col', $spans); $match_to->set_attribute('highlight', $spans < count($columns)); } } $c_index++; } } } ?> phoronix-test-suite/pts-core/objects/pts_file_io.php0000644000175000017500000000666412200010623023006 0ustar michaelmichael. */ class pts_file_io { public static function mkdir($dir, $mode = 0777, $recursive = true) { // Compared to the normal PHP mkdir, don't emit a warning/notice when the directory already exists return !is_dir($dir) && mkdir($dir, $mode, $recursive); } public static function symlink($target, $link) { // Compared to the normal PHP symlink, don't emit a warning when the symlink already exists return is_file($target) && !is_file($link) ? symlink($target, $link) : false; } public static function unlink($file) { // Compared to the normal PHP mkdir, don't emit a warning/notice when the file doesn't exist return is_file($file) && unlink($file); } public static function glob($pattern, $flags = 0) { // Compared to the normal PHP glob, don't return false when no files are there, but return an empty array $r = glob($pattern, $flags); return is_array($r) ? $r : array(); } public static function file_get_contents($filename, $flags = 0, $context = null) { // Compared to the normal PHP file_get_contents, trim the file as a string when acquired return trim(file_get_contents($filename, $flags, $context)); } public static function delete($object, $ignore_files = null, $remove_root_directory = false) { // Delete files and/or directories if($object == false) { return false; } if(is_dir($object)) { $object = pts_strings::add_trailing_slash($object); } foreach(pts_file_io::glob($object . '*') as $to_remove) { if(is_file($to_remove) || is_link($to_remove)) { if(is_array($ignore_files) && in_array(basename($to_remove), $ignore_files)) { continue; // Don't remove the file } else { unlink($to_remove); } } else if(is_dir($to_remove)) { self::delete($to_remove, $ignore_files, true); } } if($remove_root_directory && is_dir($object) && count(pts_file_io::glob($object . '/*')) == 0) { rmdir($object); } } public static function array_filesize($r) { $filesize = 0; foreach($r as $file) { if(is_file($file)) { $filesize += filesize($file); } } return $filesize; } public static function copy($source, $dest) { $success = false; if(is_file($source)) { $success = copy($source, $dest); } else if(is_link($source)) { $success = copy(readlink($source), $dest); } else if(is_dir($source)) { if(!is_dir($dest)) { mkdir($dest); } $dir = dir($source); while(($entry = $dir->read()) !== false) { if($entry == '.' || $entry == '..') { continue; } self::copy($source . '/' . $entry, $dest . '/' . $entry); } $dir->close(); $success = true; } return $success; } } ?> phoronix-test-suite/pts-core/objects/pts_pdf_template.php0000644000175000017500000002610012033147303024041 0ustar michaelmichael. */ class pts_pdf_template extends FPDF { private $pts_title = ''; private $pts_sub_title = ''; private $pdf_bookmarks = array(); private $pdf_bookmarks_outline_object_n = 0; public function __construct($Title = '', $SubTitle = '') { parent::__construct(); $this->pts_title = $Title; $this->pts_sub_title = $SubTitle; $this->SetTitle($Title); $this->SetAuthor('Phoronix Test Suite'); $this->SetCreator(pts_codename(true)); $this->SetCompression(false); } public function html_to_pdf($html) { $dom = new DOMDocument(); if(is_file($html)) { $dom->loadHTMLFile($html); } else { $dom->loadHTML($html); } $section_title = $dom->getElementsByTagName('html')->item(0)->getElementsByTagName('head')->item(0)->nodeValue; $tags = $dom->getElementsByTagName('html')->item(0)->getElementsByTagName('body')->item(0)->childNodes; $this->SetLeftMargin(8.5); $this->AddPage(); $this->CreateBookmark($section_title, 0); $this->SetFont('Arial', 'B', 21); $this->SetTextColor(50, 51, 49); $this->SetFillColor(255, 255, 255); $this->Cell(0, 6, $section_title, 0, 0, 'L', true); $this->Ln(10); for($i = 0; $i < $tags->length; $i++) { $name = $tags->item($i)->nodeName; $value = $tags->item($i)->nodeValue; $dom_item = $tags->item($i); switch($name) { case 'h1': $this->CreateBookmark($value, 1); $this->SetFont('Arial', 'B', 16); $this->SetLeftMargin(8.5); $this->SetTextColor(50, 51, 49); $this->Ln(); $this->html_text_interpret('h1', $dom_item); $this->Ln(); break; case 'h2': $this->CreateBookmark($value, 2); $this->SetLeftMargin(10); $this->SetFont('Arial', 'B', 13); $this->SetTextColor(50, 51, 49); $this->Ln(); $this->html_text_interpret('h2', $dom_item); break; case 'h3': $this->SetLeftMargin(10); $this->SetFont('Arial', 'B', 13); $this->SetTextColor(97, 99, 96); $this->Ln(); $this->html_text_interpret('h3', $dom_item); break; case 'ol': case 'ul': $this->SetFont('Arial', null, 11); $this->SetLeftMargin(30); $this->SetTextColor(0, 0, 0); $this->Ln(); foreach($tags->item($i)->childNodes as $j => $li) { if($name == 'ol' && ($j % 2) == 0) { $this->SetFont(null, 'B'); $this->Write(5, ceil($j / 2) + 1 . '. ', null); $this->SetFont(null, null); } $this->html_text_interpret('p', $li); $this->Ln(); } $this->SetLeftMargin(10); $this->Ln(); break; case 'li': $this->SetFont('Arial', null, 11); $this->SetLeftMargin(30); $this->SetTextColor(0, 0, 0); $this->html_text_interpret('li', $dom_item); $this->Ln(); break; case 'p': $this->SetFont('Arial', null, 11); $this->SetLeftMargin(20); $this->SetTextColor(0, 0, 0); $this->Ln(); $this->html_text_interpret('p', $dom_item); $this->SetLeftMargin(10); $this->Ln(); break; case 'hr': $this->Ln(8); break; } } } protected function html_text_interpret($apply_as_tag, &$dom_item) { for($j = 0; property_exists($dom_item, 'length') == false && $j < $dom_item->childNodes->length; $j++) { $value = $dom_item->childNodes->item($j)->nodeValue; $name = $dom_item->childNodes->item($j)->nodeName; switch($name) { case 'em': $this->SetFont(null, 'I', (substr($apply_as_tag, 0, 1) == 'h' ? '12' : null)); break; case 'strong': $this->SetFont(null, 'B'); break; case '#text': $this->SetFont(null, (substr($apply_as_tag, 0, 1) == 'h' ? 'B' : null)); break; case 'a': $this->SetTextColor(0, 0, 116); $this->SetFont(null, 'BU'); $this->Write(5, $value, $dom_item->childNodes->item($j)->attributes->getNamedItem('href')->nodeValue); $this->SetTextColor(0, 0, 0); break; default: echo "UNSUPPORTED: $name\n"; break; } if($name != 'a') { $this->Write(5, $value, null); } } } public function Header() { if($this->PageNo() == 1) { return; } if(is_file(PTS_CORE_STATIC_PATH . 'images/pts-158x82.jpg')) { $this->Image(PTS_CORE_STATIC_PATH . 'images/pts-158x82.jpg', 10, 8, 30); } $this->SetFont('Arial', 'B', 14); $this->Cell(80); $this->Cell(30, 10, $this->pts_title, 0, 0, 'C'); $this->Ln(6); $this->SetFont('Arial', 'B', 10); $this->Cell(0, 10, $this->pts_sub_title, 0, 0, 'C'); $this->Ln(15); } public function Footer() { if($this->PageNo() == 1) { return; } $this->SetY(-10); $this->SetFont('Arial', 'B', 7); $this->Cell(0, 0, pts_title(), 0, 0, 'L'); $this->Cell(0, 0, 'www.phoronix-test-suite.com', 0, 0, 'R', true, 'http://www.phoronix-test-suite.com/'); } public function WriteBigHeaderCenter($Header) { $this->WriteBigHeader($Header, 'C'); } public function WriteBigHeader($Header, $Align = 'L') { $this->SetFont('Arial', 'B', 21); $this->SetFillColor(255, 255, 255); $this->Cell(0, 6, $Header, 0, 0, $Align, true); $this->Ln(15); } public function WriteHeaderCenter($Header) { $this->WriteHeader($Header, 'C'); } public function WriteHeader($Header, $Align = 'L') { $this->SetFont('Arial', 'B', 16); $this->SetFillColor(255, 255, 255); $this->Cell(0, 6, $Header, 0, 0, $Align, true); $this->Ln(10); } public function WriteStatementCenter($Header) { $this->WriteStatement($Header, 'C'); } public function WriteStatement($Header, $Align = 'L', $Link = null) { $this->SetFont('Arial', 'B', 14); $this->SetFillColor(255, 255, 255); $this->Cell(0, 2, $Header, 0, 0, $Align, true, $Link); $this->Ln(10); } public function WriteMiniHeader($Header) { $this->SetFont('Arial', 'B', 13); $this->SetFillColor(255, 255, 255); $this->Cell(0, 2, $Header, 0, 0, 'L', true); $this->Ln(5); } public function WriteDocHeader($Header, $Options = null) { $this->SetFont('Arial', 'B', 12); $this->SetFillColor(255, 255, 255); $this->Write(12, $Header); if(is_array($Options)) { $this->Write(12, ' '); $this->SetFont('Arial', 'I', 10); $this->Write(12, implode(' ', $Options)); } $this->Ln(10); } public function WriteDocText($Text) { $this->SetFont('Arial', '', 10); $this->MultiCell(0, 5, $Text); } public function WriteText($Text) { $this->SetFont('Arial', '', 11); $this->MultiCell(0, 5, $Text); $this->Ln(); } public function ResultTable($headers, $data, $left_headers = '') { $this->Ln(20); $this->SetFillColor(0, 0, 0); $this->SetTextColor(255, 255, 255); $this->SetDrawColor(34, 34, 34); $this->SetLineWidth(0.3); $this->SetFont('Arial', 'B'); $cell_width = 50; $cell_large_width = $cell_width * 1.20; $table_width = 0; if(is_array($left_headers) && count($left_headers) > 0) { $this->Cell($cell_large_width, 7, '', 1, 0, 'C', true); $table_width += $cell_large_width; } for($i = 0; $i < count($headers); $i++) { $this->Cell($cell_width, 7, $headers[$i], 1, 0, 'C', true); } $this->Ln(); $this->SetFillColor(139, 143, 124); $this->SetTextColor(0); $this->SetFont('Arial'); $fill = false; for($i = 0; $i < count($data) || $i < count($left_headers); $i++) { if(isset($left_headers[$i])) { $this->Cell($cell_large_width, 6, $left_headers[$i], 'LR', 0, 'L', $fill); } if(!isset($data[$i])) { $data[$i] = array(); } for($j = 0; $j < count($data[$i]); $j++) { $this->Cell($cell_width, 6, $data[$i][$j], 'LR', 0, 'L', $fill); } $this->Ln(); $fill = !$fill; } $this->Cell($table_width + (count($data[0]) * $cell_width), 0, '', 'T'); } public function _putinfo() { $this->_out('/Producer ' . $this->_textstring('Phoronix Media')); $this->_out('/Subject ' . $this->_textstring('Phoronix-Test-Suite.com')); $this->_out('/Title ' . $this->_textstring($this->title)); $this->_out('/Subject ' . $this->_textstring($this->subject)); $this->_out('/Author ' . $this->_textstring($this->author)); $this->_out('/Keywords ' . $this->_textstring($this->keywords)); $this->_out('/Creator ' . $this->_textstring($this->creator)); $this->_out('/CreationDate ' . $this->_textstring('D:' . date('YmdHis'))); } // PDF Bookmarking Support // Example: http://www.fpdf.org/en/script/script1.php public function CreateBookmark($bookmark, $level = 0) { array_push($this->pdf_bookmarks, array( 't' => $bookmark, 'l' => $level, 'y' => (($this->h - $this->getY()) * $this->k), 'p' => $this->PageNo() )); } protected function insert_pdf_bookmarks() { $bookmark_count = count($this->pdf_bookmarks); $level = 0; $ls = array(); foreach($this->pdf_bookmarks as $i => &$o) { if($o['l'] > 0) { $this->pdf_bookmarks[$i]['parent'] = $ls[($o['l'] - 1)]; $this->pdf_bookmarks[$ls[($o['l'] - 1)]]['last'] = $i; if($o['l'] > $level) { $this->pdf_bookmarks[$ls[($o['l'] - 1)]]['first'] = $i; } } else { $this->pdf_bookmarks[$i]['parent'] = $bookmark_count; } if($o['l'] <= $level && $i > 0) { $this->pdf_bookmarks[$ls[$o['l']]]['next'] = $i; $this->pdf_bookmarks[$i]['prev'] = $ls[$o['l']]; } $ls[$o['l']] = $i; $level = $o['l']; } $n = $this->n + 1; foreach($this->pdf_bookmarks as $i => &$o) { $this->_newobj(); $this->_out('<_textstring($o['t'])); $this->_out('/Parent ' . ($n + $o['parent']) . ' 0 R'); if(isset($o['prev'])) { $this->_out('/Prev '. ($n + $o['prev']) . ' 0 R'); } if(isset($o['next'])) { $this->_out('/Next ' . ($n + $o['next']) . ' 0 R'); } if(isset($o['first'])) { $this->_out('/First ' . ($n + $o['first']) . ' 0 R'); } if(isset($o['last'])) { $this->_out('/Last ' . ($n + $o['last']) . ' 0 R'); } $this->_out(sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]', (1 + 2 * $o['p']), $o['y'])); $this->_out('/Count 0>>'); $this->_out('endobj'); } $this->_newobj(); $this->pdf_bookmarks_outline_object_n = $this->n; $this->_out('<_out('/Last ' . ($n + (isset($ls[0]) ? $ls[0] : 0)) . ' 0 R>>'); $this->_out('endobj'); } public function _putresources() { parent::_putresources(); $this->insert_pdf_bookmarks(); } public function _putcatalog() { parent::_putcatalog(); if(count($this->pdf_bookmarks) > 0) { $this->_out('/Outlines ' . $this->pdf_bookmarks_outline_object_n . ' 0 R'); $this->_out('/PageMode /UseOutlines'); } } } ?> phoronix-test-suite/pts-core/objects/pts_test_profile_downloads_writer.php0000644000175000017500000000476012222310131027541 0ustar michaelmichael. */ class pts_test_profile_downloads_writer { private $xml_writer = null; public function __construct() { $this->xml_writer = new nye_XmlWriter(); } public function get_xml() { return $this->xml_writer->getXML(); } public function save_xml($to_save) { return $this->xml_writer->saveXMLFile($to_save); } public function rebuild_download_file(&$test_profile) { foreach(pts_test_install_request::read_download_object_list($test_profile, false) as $file) { $this->add_download($file->get_download_url_string(), $file->get_md5(), $file->get_sha256(), $file->get_filename(), $file->get_filesize(), $file->get_platform_string(), $file->get_architecture_string()); } } public function add_download($url_string, $md5 = null, $sha256 = null, $file_name = null, $file_size = null, $platform_specific = null, $architecture_specific = null) { $this->xml_writer->addXmlNode('PhoronixTestSuite/Downloads/Package/URL', $url_string); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Downloads/Package/MD5', $md5); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Downloads/Package/SHA256', $sha256); if(basename($url_string) != $file_name) { // If the downloaded file is the same name as the file name, pts-core already obtains it, so having it here is redundant. $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Downloads/Package/FileName', $file_name); } $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Downloads/Package/FileSize', $file_size); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Downloads/Package/PlatformSpecific', $platform_specific); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Downloads/Package/ArchitectureSpecific', $architecture_specific); } } ?> phoronix-test-suite/pts-core/objects/pts_test_profile.php0000644000175000017500000003047312105330411024076 0ustar michaelmichael. */ class pts_test_profile extends pts_test_profile_parser { public $test_installation = false; public function __construct($identifier = null, $override_values = null) { parent::__construct($identifier); if($override_values != null && is_array($override_values)) { $this->xml_parser->overrideXMLValues($override_values); } if(PTS_IS_CLIENT && is_file($this->get_install_dir() . 'pts-install.xml')) { $this->test_installation = new pts_installed_test($this); } } public static function is_test_profile($identifier) { $identifier = pts_openbenchmarking::evaluate_string_to_qualifier($identifier, true, 'test'); return $identifier != false && is_file(PTS_TEST_PROFILE_PATH . $identifier . '/test-definition.xml') ? $identifier : false; } public function get_resource_dir() { return PTS_TEST_PROFILE_PATH . $this->identifier . '/'; } public function get_override_values() { return $this->xml_parser->getOverrideValues(); } public function set_override_values($override_values) { if(is_array($override_values)) { $this->xml_parser->overrideXMLValues($override_values); } } public function get_download_size($include_extensions = true, $divider = 1048576) { $estimated_size = 0; foreach(pts_test_install_request::read_download_object_list($this->identifier) as $download_object) { $estimated_size += $download_object->get_filesize(); } if($include_extensions) { $extends = $this->get_test_extension(); if(!empty($extends)) { $test_profile = new pts_test_profile($extends); $estimated_size += $test_profile->get_download_size(true, 1); } } $estimated_size = $estimated_size > 0 && $divider > 1 ? round($estimated_size / $divider, 2) : 0; return $estimated_size; } public function get_environment_size($include_extensions = true) { $estimated_size = parent::get_environment_size(); if($include_extensions) { $extends = $this->get_test_extension(); if(!empty($extends)) { $test_profile = new pts_test_profile($extends); $estimated_size += $test_profile->get_environment_size(true); } } return $estimated_size; } public function get_test_extensions_recursive() { // Process Extensions / Cascading Test Profiles $extensions = array(); $extended_test = $this->get_test_extension(); if(!empty($extended_test)) { do { if(!in_array($extended_test, $extensions)) { array_push($extensions, $extended_test); } $extended_test = new pts_test_profile_parser($extended_test); $extended_test = $extended_test->get_test_extension(); } while(!empty($extended_test)); } return $extensions; } public function get_dependency_names() { $dependency_names = array(); $exdep_generic_parser = new pts_exdep_generic_parser(); foreach($this->get_dependencies() as $dependency) { if($exdep_generic_parser->is_package($dependency)) { $package_data = $exdep_generic_parser->get_package_data($dependency); array_push($dependency_names, $package_data['title']); break; } } return $dependency_names; } public function get_times_to_run() { $times_to_run = parent::get_times_to_run(); if(($force_runs = pts_client::read_env('FORCE_TIMES_TO_RUN')) && is_numeric($force_runs)) { $times_to_run = $force_runs; } if(($force_runs = pts_client::read_env('FORCE_MIN_TIMES_TO_RUN')) && is_numeric($force_runs) && $force_runs > $times_to_run) { $times_to_run = $force_runs; } $display_format = $this->get_display_format(); if($times_to_run < 1 || (strlen($display_format) > 6 && substr($display_format, 0, 6) == 'MULTI_' || substr($display_format, 0, 6) == 'IMAGE_')) { // Currently tests that output multiple results in one run can only be run once $times_to_run = 1; } return $times_to_run; } public function get_estimated_run_time() { // get estimated run-time (in seconds) if($this->test_installation != false && is_numeric($this->test_installation->get_average_run_time()) && $this->test_installation->get_average_run_time() > 0) { $estimated_run_time = $this->test_installation->get_average_run_time(); } else { $estimated_run_time = parent::get_estimated_run_time(); } if($estimated_run_time < 2 && PTS_IS_CLIENT) { $identifier = explode('/', $this->get_identifier(false)); $repo_index = pts_openbenchmarking::read_repository_index($identifier[0]); $estimated_run_time = isset($identifier[1]) && isset($repo_index['tests'][$identifier[1]]) && isset($repo_index['tests'][$identifier[1]]['average_run_time']) ? $repo_index['tests'][$identifier[1]]['average_run_time'] : 0; } return $estimated_run_time; } public function is_supported($report_warnings = true) { $test_supported = true; if(PTS_IS_CLIENT && pts_client::read_env('SKIP_TEST_SUPPORT_CHECKS')) { // set SKIP_TEST_SUPPORT_CHECKS=1 environment variable for debugging purposes to run tests on unsupported platforms return true; } if($this->is_test_architecture_supported() == false) { PTS_IS_CLIENT && $report_warnings && pts_client::$display->test_run_error($this->get_identifier() . ' is not supported on this architecture: ' . phodevi::read_property('system', 'kernel-architecture')); $test_supported = false; } else if($this->is_test_platform_supported() == false) { PTS_IS_CLIENT && $report_warnings && pts_client::$display->test_run_error($this->get_identifier() . ' is not supported by this operating system: ' . phodevi::operating_system()); $test_supported = false; } else if($this->is_core_version_supported() == false) { PTS_IS_CLIENT && $report_warnings && pts_client::$display->test_run_error($this->get_identifier() . ' is not supported by this version of the Phoronix Test Suite: ' . PTS_VERSION); $test_supported = false; } else if(PTS_IS_CLIENT && ($custom_support_check = $this->custom_test_support_check()) !== true) { // A custom-self-generated error occurred, see code comments in custom_test_support_check() PTS_IS_CLIENT && $report_warnings && pts_client::$display->test_run_error($this->get_identifier() . ': ' . $custom_support_check); $test_supported = false; } return $test_supported; } public function custom_test_support_check() { /* As of Phoronix Test Suite 4.4, the software will check for the presence of a 'support-check' file. Any test profile can optionally include a support-check.sh file to check for arbitrary commands not covered by the rest of the PTS testing architecture, e.g. to check for the presence of systemd on the target system. If the script finds that the system is incompatible with the test, it can write a custom error message to the file specified by the $TEST_CUSTOM_ERROR environment variable. If the $TEST_CUSTOM_ERROR target is written to, the PTS client will abort the test installation with the specified error message. */ $support_check_file = $this->get_resource_dir() . 'support-check.sh'; if(PTS_IS_CLIENT && is_file($support_check_file)) { $environment['TEST_CUSTOM_ERROR'] = pts_client::temporary_directory() . '/PTS-' . $this->get_identifier_base_name() . '-' . rand(1000, 9999); $support_check = pts_tests::call_test_script($this, 'support-check', null, null, $environment, false); if(is_file($environment['TEST_CUSTOM_ERROR'])) { $support_result = pts_file_io::file_get_contents($environment['TEST_CUSTOM_ERROR']); pts_file_io::delete($environment['TEST_CUSTOM_ERROR']); return $support_result; } } return true; } public function is_test_architecture_supported() { // Check if the system's architecture is supported by a test $supported = true; $archs = $this->get_supported_architectures(); if(!empty($archs)) { $supported = phodevi::cpu_arch_compatible($archs); } return $supported; } public function is_core_version_supported() { // Check if the test profile's version is compatible with pts-core $core_version_min = parent::requires_core_version_min(); $core_version_max = parent::requires_core_version_max(); return $core_version_min <= PTS_CORE_VERSION && $core_version_max > PTS_CORE_VERSION; } public function is_test_platform_supported() { // Check if the system's OS is supported by a test $supported = true; $platforms = $this->get_supported_platforms(); if(!empty($platforms) && !in_array(phodevi::operating_system(), $platforms)) { if(phodevi::is_bsd() && in_array('Linux', $platforms) && (pts_client::executable_in_path('kldstat') && strpos(shell_exec('kldstat -n linux 2>&1'), 'linux.ko') != false)) { // The OS is BSD but there is Linux API/ABI compatibility support loaded $supported = true; } else if(phodevi::is_hurd() && in_array('Linux', $platforms) && in_array('BSD', $platforms)) { // For now until test profiles explicity express Hurd support, just list as supported the tests that work on both BSD and Linux // TODO: fill in Hurd support for test profiles / see what works $supported = true; } else { $supported = false; } } return $supported; } public static function generate_comparison_hash($test_identifier, $arguments, $attributes = null, $version = null) { $hash_table = array( $test_identifier, trim($arguments), trim($attributes), $version ); return sha1(implode(',', $hash_table), true); } public function get_test_executable_dir() { $to_execute = null; $test_dir = $this->get_install_dir(); $execute_binary = $this->get_test_executable(); if(is_executable($test_dir . $execute_binary) || (phodevi::is_windows() && is_file($test_dir . $execute_binary))) { $to_execute = $test_dir; } return $to_execute; } public function is_test_installed() { return is_file($this->get_install_dir() . 'pts-install.xml'); } public function get_install_dir() { return pts_client::test_install_root_path() . $this->identifier . '/'; } public function get_installer_checksum() { return $this->get_file_installer() != false ? md5_file($this->get_file_installer()) : false; } public function get_file_installer() { $test_resources_location = $this->get_resource_dir(); $os_postfix = '_' . strtolower(phodevi::operating_system()); if(is_file($test_resources_location . 'install' . $os_postfix . '.sh')) { $installer = $test_resources_location . 'install' . $os_postfix . '.sh'; } else if(is_file($test_resources_location . 'install.sh')) { $installer = $test_resources_location . 'install.sh'; } else { $installer = null; } return $installer; } public function get_file_download_spec() { return is_file($this->get_resource_dir() . 'downloads.xml') ? $this->get_resource_dir() . 'downloads.xml' : false; } public function get_file_parser_spec() { return is_file($this->get_resource_dir() . 'results-definition.xml') ? $this->get_resource_dir() . 'results-definition.xml' : false; } public function extended_test_profiles() { // Provide an array containing the location(s) of all test(s) for the supplied object name $test_profiles = array(); foreach(array_unique(array_reverse($this->get_test_extensions_recursive())) as $extended_test) { $test_profile = new pts_test_profile($extended_test); array_push($test_profiles, $test_profile); } return $test_profiles; } public function needs_updated_install() { // Checks if test needs updating // || $this->test_installation->get_installed_system_identifier() != phodevi::system_id_string() return $this->test_installation == false || $this->get_test_profile_version() != $this->test_installation->get_installed_version() || $this->get_installer_checksum() != $this->test_installation->get_installed_checksum() || (pts_c::$test_flags & pts_c::force_install); } } ?> phoronix-test-suite/pts-core/objects/pts_result_file.php0000644000175000017500000002255012105336333023722 0ustar michaelmichael. */ class pts_result_file { private $save_identifier = null; private $result_objects = null; private $extra_attributes = null; private $is_multi_way_inverted = false; public $xml_parser = null; public function __construct($result_file) { $this->save_identifier = $result_file; $this->xml_parser = new pts_results_nye_XmlReader($result_file); $this->extra_attributes = array(); } public function __toString() { return $this->get_identifier(); } public static function is_test_result_file($identifier) { return is_file(PTS_SAVE_RESULTS_PATH . $identifier . '/composite.xml'); } public function get_identifier() { return $this->save_identifier; } public function read_extra_attribute($key) { return isset($this->extra_attributes[$key]) ? $this->extra_attributes[$key] : false; } public function set_extra_attribute($key, $value) { $this->extra_attributes[$key] = $value; } public function get_system_hardware() { return $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/System/Hardware'); } public function get_system_software() { return $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/System/Software'); } public function get_system_json() { return array_map(array('pts_arrays', 'json_decode'), $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/System/JSON')); } public function get_system_user() { return $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/System/User'); } public function get_system_notes() { return $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/System/Notes'); } public function get_system_date() { return $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/System/TimeStamp'); } public function get_system_pts_version() { return $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/System/TestClientVersion'); } public function get_system_identifiers() { return $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/System/Identifier'); } public function get_system_count() { return count($this->get_system_identifiers()); } public function get_title() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/Generated/Title'); } public function get_description() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/Generated/Description'); } public function get_notes() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/Generated/Notes'); } public function get_internal_tags() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/Generated/InternalTags'); } public function get_reference_id() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/Generated/ReferenceID'); } public function get_preset_environment_variables() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/Generated/PreSetEnvironmentVariables'); } public function get_test_titles() { return $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Result/Title'); } public function get_unique_test_titles() { return array_unique($this->get_test_titles()); } public function get_test_count() { return count($this->get_test_titles()); } public function get_unique_test_count() { return count($this->get_unique_test_titles()); } public function get_contained_tests_hash() { $result_object_hashes = $this->get_result_object_hashes(); sort($result_object_hashes); return sha1(implode(',', $result_object_hashes), true); } public function get_result_object_hashes() { $object_hashes = array(); foreach($this->get_result_objects() as $result_object) { array_push($object_hashes, $result_object->get_comparison_hash()); } return $object_hashes; } public function is_results_tracker() { // If there are more than five results and the only changes in the system identifier names are numeric changes, assume it's a tracker // i.e. different dates or different versions of a package being tested static $is_tracker = -1; if($is_tracker === -1) { $identifiers = $this->get_system_identifiers(); if(isset($identifiers[4])) { // dirty SHA1 hash check $is_sha1_hash = strlen($identifiers[0]) == 40 && strpos($identifiers[0], ' ') === false; $has_sha1_shorthash = false; foreach($identifiers as $i => &$identifier) { $has_sha1_shorthash = ($i == 0 || $has_sha1_shorthash) && isset($identifier[7]) && pts_strings::string_only_contains(substr($identifier, -8), pts_strings::CHAR_NUMERIC | pts_strings::CHAR_LETTER) && strpos($identifier, ' ') === false; $identifier = pts_strings::remove_from_string($identifier, pts_strings::CHAR_NUMERIC | pts_strings::CHAR_DASH | pts_strings::CHAR_DECIMAL); } $is_tracker = count(array_unique($identifiers)) <= 1 || $is_sha1_hash || $has_sha1_shorthash; if($is_tracker) { $hw = $this->get_system_hardware(); if(isset($hw[1]) && count($hw) == count(array_unique($hw))) { // it can't be a results tracker if the hardware is always different $is_tracker = false; } } } else { // Definitely not a tracker as not over 5 results $is_tracker = false; } } return $is_tracker; } public function is_multi_way_comparison() { static $is_multi_way = -1; if($is_multi_way === -1) { $hw = $this->get_system_hardware(); $is_multi_way = count($hw) < 2 ? false : pts_render::multi_way_identifier_check($this->get_system_identifiers(), $hw, $this); $this->is_multi_way_inverted = $is_multi_way && $is_multi_way[1]; } return $is_multi_way; } public function invert_multi_way_invert() { $this->is_multi_way_inverted = ($this->is_multi_way_inverted == false); } public function is_multi_way_inverted() { return $this->is_multi_way_inverted; } public function get_contained_test_profiles() { $test_profiles = array(); foreach($this->get_result_objects() as $object) { array_push($test_profiles, $object->test_profile); } return $test_profiles; } public function override_result_objects($result_objects) { $this->result_objects = $result_objects; } public function get_result_objects($select_indexes = -1) { if($this->result_objects == null) { $this->result_objects = array(); $results_name = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Result/Title'); $results_version = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Result/AppVersion'); $results_attributes = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Result/Description'); $results_scale = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Result/Scale'); $results_test_name = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Result/Identifier'); $results_arguments = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Result/Arguments'); $results_proportion = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Result/Proportion'); $results_format = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Result/DisplayFormat'); $results_identifiers = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Result/Data/Entry/Identifier', 0); $results_values = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Result/Data/Entry/Value', 0); $results_raw = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Result/Data/Entry/RawString', 0); $results_json = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Result/Data/Entry/JSON', 0); for($i = 0; $i < count($results_name); $i++) { $test_profile = new pts_test_profile($results_test_name[$i]); $test_profile->set_test_title($results_name[$i]); $test_profile->set_version($results_version[$i]); $test_profile->set_result_scale($results_scale[$i]); $test_profile->set_result_proportion($results_proportion[$i]); $test_profile->set_display_format($results_format[$i]); $test_result = new pts_test_result($test_profile); $test_result->set_used_arguments_description($results_attributes[$i]); $test_result->set_used_arguments($results_arguments[$i]); $result_buffer = new pts_test_result_buffer(); for($j = 0; $j < count($results_identifiers[$i]); $j++) { $result_buffer->add_test_result($results_identifiers[$i][$j], $results_values[$i][$j], $results_raw[$i][$j], (isset($results_json[$i][$j]) ? $results_json[$i][$j] : null)); } $test_result->set_test_result_buffer($result_buffer); array_push($this->result_objects, $test_result); } } if($select_indexes != -1) { $objects = array(); foreach(pts_arrays::to_array($select_indexes) as $index) { if(isset($this->result_objects[$index])) { array_push($objects, $this->result_objects[$index]); } } return $objects; } return $this->result_objects; } } ?> phoronix-test-suite/pts-core/objects/pts_test_result.php0000644000175000017500000001336012171653662023773 0ustar michaelmichael. */ class pts_test_result { // Note in most pts-core code the initialized var is called $result_object // Note in pts-core code the initialized var is also called $test_run_request private $result = 0; private $result_min = 0; private $result_max = 0; private $used_arguments; private $used_arguments_description; public $test_profile; public $test_result_buffer; public $active_result = null; public $active_min_result = null; public $active_max_result = null; public $secondary_linked_results = null; public function __construct(&$test_profile) { $this->test_profile = $test_profile; $this->result = 0; } public function __clone() { $this->test_profile = clone $this->test_profile; } public function set_test_result_buffer($test_result_buffer) { $this->test_result_buffer = $test_result_buffer; } public function set_used_arguments_description($arguments_description) { $this->used_arguments_description = $arguments_description; } public function set_used_arguments($used_arguments) { $this->used_arguments = $used_arguments; } public function get_arguments() { return $this->used_arguments; } public function get_arguments_description() { return $this->used_arguments_description; } public function set_result($result) { $this->result = $result; } public function set_min_result($result) { $this->result_min = $result; } public function set_max_result($result) { $this->result_max = $result; } public function get_result() { return $this->result; } public function get_min_result() { return $this->result_min; } public function get_max_result() { return $this->result_max; } public function get_comparison_hash($show_version_and_attributes = true) { if($show_version_and_attributes) { $tp = $this->test_profile->get_identifier(true); // remove the last segment of the test profile version that should be in xx.yy.zz format // this removal is done since the zz segment should be maintainable between comparisons $tp = substr($tp, 0, strrpos($tp, '.')); return pts_test_profile::generate_comparison_hash($tp, $this->get_arguments(), $this->get_arguments_description(), $this->test_profile->get_app_version()); } else { return pts_test_profile::generate_comparison_hash($this->test_profile->get_identifier(false), $this->get_arguments()); } } public function __toString() { return $this->test_profile->get_identifier(false) . ' ' . $this->get_arguments() . ' ' . $this->get_arguments_description() . ' ' . $this->test_profile->get_override_values(); } public function normalize_buffer_values($normalize_against = false) { if($this->test_profile->get_display_format() != 'BAR_GRAPH') // BAR_ANALYZE_GRAPH is currently unsupported { 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(); } } } foreach($keys as $k) { $normalized = pts_math::set_precision(($this->test_result_buffer->buffer_items[$k]->get_result_value() / $divide_value), 2); $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; } } ?> phoronix-test-suite/pts-core/objects/pts_test_result_parser.php0000644000175000017500000006045712171774740025361 0ustar michaelmichael. */ class pts_test_result_parser { private static $supported_sensors = null; private static $monitoring_sensors = array(); public static function system_monitor_task_check(&$test_profile) { $parse_xml_file = $test_profile->get_file_parser_spec(); if($parse_xml_file == false) { return false; } self::$monitoring_sensors = array(); $test_directory = $test_profile->get_install_dir(); $results_parser_xml = new pts_parse_results_nye_XmlReader($parse_xml_file); $monitor_sensor = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/SystemMonitor/Sensor'); $monitor_frequency = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/SystemMonitor/PollingFrequency'); $monitor_report_as = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/SystemMonitor/Report'); if(count($monitor_sensor) == 0) { // No monitoring to do return false; } if(self::$supported_sensors == null) { // Cache this since this shouldn't change between tests/runs self::$supported_sensors = phodevi::supported_sensors(); } foreach(array_keys($monitor_sensor) as $i) { // TODO: Right now we are looping through SystemMonitor tags, but right now pts-core only supports providing one monitor sensor as the result $sensor = explode('.', $monitor_sensor[$i]); if($sensor == array('sys', 'time')) { // sys.time is a special case since we are just timing the test length and thus don't need to fork the thread $start_time = microtime(true); array_push(self::$monitoring_sensors, array(0, $sensor, null, $start_time)); continue; } if(count($sensor) != 2 || !in_array($sensor, self::$supported_sensors)) { // Not a sensor or it's not supported continue; } if(!is_numeric($monitor_frequency[$i]) || $monitor_frequency < 0.5) { // No polling frequency supplied continue; } $monitor_frequency[$i] *= 1000000; // Convert from seconds to micro-seconds if(!in_array($monitor_report_as[$i], array('ALL', 'MAX', 'MIN', 'AVG'))) { // Not a valid reporting type continue; } if(!function_exists('pcntl_fork')) { pts_client::$display->test_run_instance_error('PHP with PCNTL support enabled is required for this test.'); return false; } $monitor_file = tempnam($test_directory, '.monitor'); $pid = pcntl_fork(); if($pid != -1) { if($pid) { // Main process still array_push(self::$monitoring_sensors, array($pid, $sensor, $monitor_report_as[$i], $monitor_file)); continue; } else { $sensor_values = array(); while(is_file(PTS_USER_LOCK)) // TODO: or perhaps it may be okay to just do while(true) since posix_kill() is used when needed { array_push($sensor_values, phodevi::read_sensor($sensor)); file_put_contents($monitor_file, implode("\n", $sensor_values)); usleep($monitor_frequency[$i]); } exit(0); } } } return count(self::$monitoring_sensors) > 0; } public static function system_monitor_task_post_test(&$test_profile) { $test_directory = $test_profile->get_install_dir(); foreach(self::$monitoring_sensors as $sensor_r) { if($sensor_r[1] == array('sys', 'time')) { // sys.time is a special case $end_time = microtime(true); // Delta time $result_value = $end_time - $sensor_r[3]; if($result_value < 3) { // The test ended too fast $result_value = null; } } else { // Kill the sensor monitoring thread if(function_exists('posix_kill') == false) { pts_client::$display->test_run_error('The PHP POSIX extension is required for this test.'); return false; } posix_kill($sensor_r[0], SIGTERM); $sensor_values = explode("\n", pts_file_io::file_get_contents($sensor_r[3])); pts_file_io::unlink($sensor_r[3]); if(count($sensor_values) == 0) { continue; } switch($sensor_r[2]) { case 'MAX': $result_value = max($sensor_values); break; case 'MIN': $result_value = min($sensor_values); break; case 'AVG': $result_value = array_sum($sensor_values) / count($sensor_values); break; case 'ALL': $result_value = implode(',', $sensor_values); break; default: $result_value = null; break; } } if($result_value != null) { // For now it's only possible to return one result per test return $result_value; } } return false; } public static function parse_result(&$test_run_request, $test_log_file) { $parse_xml_file = $test_run_request->test_profile->get_file_parser_spec(); if($parse_xml_file == false) { return null; } $test_identifier = $test_run_request->test_profile->get_identifier(); $extra_arguments = $test_run_request->get_arguments(); $pts_test_arguments = trim($test_run_request->test_profile->get_default_arguments() . ' ' . str_replace($test_run_request->test_profile->get_default_arguments(), '', $extra_arguments) . ' ' . $test_run_request->test_profile->get_default_post_arguments()); switch($test_run_request->test_profile->get_display_format()) { case 'IMAGE_COMPARISON': $test_run_request->active_result = self::parse_iqc_result($test_run_request->test_profile, $parse_xml_file, $test_log_file, $pts_test_arguments, $extra_arguments); break; case 'PASS_FAIL': case 'MULTI_PASS_FAIL': $test_run_request->active_result = self::parse_generic_result($test_identifier, $parse_xml_file, $test_log_file, $pts_test_arguments, $extra_arguments); break; case 'BAR_GRAPH': default: $test_run_request->active_result = self::parse_numeric_result($test_identifier, $parse_xml_file, $test_log_file, $pts_test_arguments, $extra_arguments); if($test_run_request->test_profile->get_display_format() == 'BAR_GRAPH' && !is_numeric($test_run_request->active_result)) { $test_run_request->active_result = false; } else { $test_run_request->active_min_result = self::parse_numeric_result($test_identifier, $parse_xml_file, $test_log_file, $pts_test_arguments, $extra_arguments, 'MIN'); $test_run_request->active_max_result = self::parse_numeric_result($test_identifier, $parse_xml_file, $test_log_file, $pts_test_arguments, $extra_arguments, 'MAX'); } break; } } public static function generate_extra_data(&$test_result, &$test_log_file = null) { $parse_xml_file = $test_result->test_profile->get_file_parser_spec(); if($parse_xml_file == false) { return; } $results_parser_xml = new pts_parse_results_nye_XmlReader($parse_xml_file); $extra_data_identifiers = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ExtraData/Identifier'); $extra_results = array(); foreach(array_keys($extra_data_identifiers) as $i) { $id = $extra_data_identifiers[$i]; switch($id) { case 'com-speeds-frame-latency-totals': $log_file = pts_file_io::file_get_contents($test_log_file); $frame_all_times = array(); while(($log_file = strstr($log_file, 'frame:'))) { if(($a = strpos($log_file, ' all: ')) !== false && $a < strpos($log_file, "\n")) { $all = ltrim(substr($log_file, $a + 6)); $all = substr($all, 0, strpos($all, ' ')); if(is_numeric($all) && $all > 0) { array_push($frame_all_times, $all); } } $log_file = strstr($log_file, 'bk:'); } if(isset($frame_all_times[60])) { // Take off the first frame as it's likely to have taken much longer when game just starting off... array_shift($frame_all_times); $tp = clone $test_result->test_profile; $tp->set_result_scale('Milliseconds'); $tp->set_result_proportion('LIB'); $tp->set_display_format('LINE_GRAPH'); $tp->set_identifier(null); $extra_result = new pts_test_result($tp); $extra_result->set_used_arguments_description('Total Frame Time'); $extra_result->set_result(implode(',', $frame_all_times)); array_push($extra_results, $extra_result); //$extra_result->set_used_arguments(phodevi::sensor_name($sensor) . ' ' . $test_result->get_arguments()); } break; } } if(!empty($extra_results)) { $test_result->secondary_linked_results = $extra_results; } } public static function calculate_end_result(&$test_result) { $trial_results = $test_result->test_result_buffer->get_values(); if(count($trial_results) == 0) { $test_result->set_result(0); return false; } $END_RESULT = 0; switch($test_result->test_profile->get_display_format()) { case 'NO_RESULT': // Nothing to do, there are no results break; case 'LINE_GRAPH': case 'FILLED_LINE_GRAPH': case 'TEST_COUNT_PASS': // Just take the first result $END_RESULT = $trial_results[0]; break; case 'IMAGE_COMPARISON': // Capture the image $iqc_image_png = $trial_results[0]; if(is_file($iqc_image_png)) { $img_file_64 = base64_encode(file_get_contents($iqc_image_png, FILE_BINARY)); $END_RESULT = $img_file_64; unlink($iqc_image_png); } break; case 'PASS_FAIL': case 'MULTI_PASS_FAIL': // Calculate pass/fail type $END_RESULT = -1; if(count($trial_results) == 1) { $END_RESULT = $trial_results[0]; } else { foreach($trial_results as $result) { if($result == 'FALSE' || $result == '0' || $result == 'FAIL') { if($END_RESULT == -1 || $END_RESULT == 'PASS') { $END_RESULT = 'FAIL'; } } else { if($END_RESULT == -1) { $END_RESULT = 'PASS'; } } } } break; case 'BAR_GRAPH': default: // Result is of a normal numerical type switch($test_result->test_profile->get_result_quantifier()) { case 'MAX': $END_RESULT = max($trial_results); break; case 'MIN': $END_RESULT = min($trial_results); break; case 'AVG': default: // assume AVG (average) $is_float = false; $TOTAL_RESULT = 0; $TOTAL_COUNT = 0; foreach($trial_results as $result) { $result = trim($result); if(is_numeric($result)) { $TOTAL_RESULT += $result; $TOTAL_COUNT++; if(!$is_float && strpos($result, '.') !== false) { $is_float = true; } } } $END_RESULT = pts_math::set_precision($TOTAL_RESULT / ($TOTAL_COUNT > 0 ? $TOTAL_COUNT : 1), 2); if(!$is_float) { $END_RESULT = round($END_RESULT); } if(count($min = $test_result->test_result_buffer->get_min_values()) > 0) { $min = round(min($min), 2); if($min < $END_RESULT && is_numeric($min) && $min != 0) { $test_result->set_min_result($min); } } if(count($max = $test_result->test_result_buffer->get_max_values()) > 0) { $max = round(max($max), 2); if($max > $END_RESULT && is_numeric($max) && $max != 0) { $test_result->set_max_result($max); } } break; } break; } $test_result->set_result($END_RESULT); } protected static function parse_iqc_result(&$test_profile, $parse_xml_file, $log_file, $pts_test_arguments, $extra_arguments) { $results_parser_xml = new pts_parse_results_nye_XmlReader($parse_xml_file); $result_match_test_arguments = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ImageParser/MatchToTestArguments'); $result_iqc_source_file = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ImageParser/SourceImage'); $result_iqc_image_x = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ImageParser/ImageX'); $result_iqc_image_y = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ImageParser/ImageY'); $result_iqc_image_width = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ImageParser/ImageWidth'); $result_iqc_image_height = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ImageParser/ImageHeight'); $test_result = false; if(!extension_loaded('gd')) { // Needs GD library to work return false; } for($i = 0; $i < count($result_iqc_source_file); $i++) { if(!empty($result_match_test_arguments[$i]) && strpos($pts_test_arguments, $result_match_test_arguments[$i]) === false) { // This is not the ResultsParser XML section to use as the MatchToTestArguments does not match the PTS test arguments continue; } if(is_file($test_profile->get_install_dir() . $result_iqc_source_file[$i])) { $iqc_source_file = $test_profile->get_install_dir() . $result_iqc_source_file[$i]; } else { // No image file found continue; } $img = pts_image::image_file_to_gd($iqc_source_file); if($img == false) { return; } $img_sliced = imagecreatetruecolor($result_iqc_image_width[$i], $result_iqc_image_height[$i]); imagecopyresampled($img_sliced, $img, 0, 0, $result_iqc_image_x[$i], $result_iqc_image_y[$i], $result_iqc_image_width[$i], $result_iqc_image_height[$i], $result_iqc_image_width[$i], $result_iqc_image_height[$i]); $test_result = $test_profile->get_install_dir() . 'iqc.png'; imagepng($img_sliced, $test_result); if($test_result != false) { break; } } return $test_result; } protected static function parse_numeric_result($test_identifier, $parse_xml_file, $log_file, $pts_test_arguments, $extra_arguments, $prefix = null) { return self::parse_result_process($test_identifier, $parse_xml_file, $log_file, $pts_test_arguments, $extra_arguments, true, $prefix); } protected static function parse_generic_result($test_identifier, $parse_xml_file, $log_file, $pts_test_arguments, $extra_arguments, $prefix = null) { return self::parse_result_process($test_identifier, $parse_xml_file, $log_file, $pts_test_arguments, $extra_arguments, false, $prefix); } protected static function parse_result_process($test_identifier, $parse_xml_file, $log_file, $pts_test_arguments, $extra_arguments, $is_numeric_check = true, $prefix = null) { $results_parser_xml = new pts_parse_results_nye_XmlReader($parse_xml_file); $result_match_test_arguments = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ResultsParser/MatchToTestArguments'); $result_template = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ResultsParser/OutputTemplate'); $result_key = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ResultsParser/ResultKey'); $result_line_hint = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ResultsParser/LineHint'); $result_line_before_hint = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ResultsParser/LineBeforeHint'); $result_line_after_hint = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ResultsParser/LineAfterHint'); $result_before_string = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ResultsParser/ResultBeforeString'); $result_divide_by = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ResultsParser/DivideResultBy'); $result_multiply_by = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ResultsParser/MultiplyResultBy'); $strip_from_result = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ResultsParser/StripFromResult'); $strip_result_postfix = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ResultsParser/StripResultPostfix'); $multi_match = $results_parser_xml->getXMLArrayValues('PhoronixTestSuite/ResultsParser/MultiMatch'); $test_result = false; if($prefix != null && substr($prefix, -1) != '_') { $prefix .= '_'; } for($i = 0; $i < count($result_template); $i++) { if(!empty($result_match_test_arguments[$i]) && strpos($pts_test_arguments, $result_match_test_arguments[$i]) === false) { // This is not the ResultsParser XML section to use as the MatchToTestArguments does not match the PTS test arguments continue; } if($result_key[$i] == null) { $result_key[$i] = '#_' . $prefix . 'RESULT_#'; } else { switch($result_key[$i]) { case 'PTS_TEST_ARGUMENTS': $result_key[$i] = '#_' . $prefix . str_replace(' ', '', $pts_test_arguments) . '_#'; break; case 'PTS_USER_SET_ARGUMENTS': $result_key[$i] = '#_' . $prefix . str_replace(' ', '', $extra_arguments) . '_#'; break; } } // The actual parsing here $start_result_pos = strrpos($result_template[$i], $result_key[$i]); if($prefix != null && $start_result_pos === false) { // XXX: technically the $prefix check shouldn't be needed, verify whether safe to have this check be unconditional on start_result_pos failing... return false; } $space_out_chars = array('(', ')', "\t"); if((isset($result_template[$i][($start_result_pos - 1)]) && $result_template[$i][($start_result_pos - 1)] == '/') || (isset($result_template[$i][($start_result_pos + strlen($result_key[$i]))]) && $result_template[$i][($start_result_pos + strlen($result_key[$i]))] == '/')) { array_push($space_out_chars, '/'); } $end_result_pos = $start_result_pos + strlen($result_key[$i]); $end_result_line_pos = strpos($result_template[$i], "\n", $end_result_pos); $result_template_line = substr($result_template[$i], 0, ($end_result_line_pos === false ? strlen($result_template[$i]) : $end_result_line_pos)); $result_template_line = substr($result_template_line, strrpos($result_template_line, "\n")); $result_template_r = explode(' ', pts_strings::trim_spaces(str_replace($space_out_chars, ' ', str_replace('=', ' = ', $result_template_line)))); $result_template_r_pos = array_search($result_key[$i], $result_template_r); if($result_template_r_pos === false) { // Look for an element that partially matches, if like a '.' or '/sec' or some other pre/post-fix is present foreach($result_template_r as $i => $r_check) { if(isset($result_key[$i]) && strpos($r_check, $result_key[$i]) !== false) { $result_template_r_pos = $i; break; } } } $search_key = null; $line_before_key = null; if(isset($result_line_hint[$i]) && $result_line_hint[$i] != null && strpos($result_template_line, $result_line_hint[$i]) !== false) { $search_key = $result_line_hint[$i]; } else if(isset($result_line_before_hint[$i]) && $result_line_before_hint[$i] != null && strpos($result_template[$i], $result_line_hint[$i]) !== false) { $search_key = null; // doesn't really matter what this value is } else if(isset($result_line_after_hint[$i]) && $result_line_after_hint[$i] != null && strpos($result_template[$i], $result_line_hint[$i]) !== false) { $search_key = null; // doesn't really matter what this value is } else { foreach($result_template_r as $line_part) { if(strpos($line_part, ':') !== false && strlen($line_part) > 1) { // add some sort of && strrpos($result_template[$i], $line_part) to make sure there isn't two of the same $search_key $search_key = $line_part; break; } } if($search_key == null && isset($result_key[$i])) { // Just try searching for the first part of the string /* for($i = 0; $i < $result_template_r_pos; $i++) { $search_key .= $result_template_r[$i] . ' '; } */ // This way if there are ) or other characters stripped, the below method will work where the above one will not $search_key = substr($result_template_line, 0, strpos($result_template_line, $result_key[$i])); } } if(is_file($log_file)) { $result_output = file_get_contents($log_file); } else { // Nothing to parse return false; } $test_results = array(); if($search_key != null || (isset($result_line_before_hint[$i]) && $result_line_before_hint[$i] != null) || (isset($result_line_after_hint[$i]) && $result_line_after_hint[$i]) != null || (isset($result_key[$i]) && $result_template_r[0] == $result_key[$i])) { $is_multi_match = !empty($multi_match[$i]) && $multi_match[$i] != 'NONE'; do { $result_count = count($test_results); if($result_line_before_hint[$i] != null) { pts_client::test_profile_debug_message('Result Parsing Line Before Hint: ' . $result_line_before_hint[$i]); $result_line = substr($result_output, strpos($result_output, "\n", strrpos($result_output, $result_line_before_hint[$i]))); $result_line = substr($result_line, 0, strpos($result_line, "\n", 1)); $result_output = substr($result_output, 0, strrpos($result_output, "\n", strrpos($result_output, $result_line_before_hint[$i]))) . "\n"; } else if($result_line_after_hint[$i] != null) { pts_client::test_profile_debug_message('Result Parsing Line After Hint: ' . $result_line_after_hint[$i]); $result_line = substr($result_output, 0, strrpos($result_output, "\n", strrpos($result_output, $result_line_before_hint[$i]))); $result_line = substr($result_line, strrpos($result_line, "\n", 1) + 1); $result_output = null; } else if($search_key != null) { $search_key = trim($search_key); pts_client::test_profile_debug_message('Result Parsing Search Key: ' . $search_key); $result_line = substr($result_output, 0, strpos($result_output, "\n", strrpos($result_output, $search_key))); $start_of_line = strrpos($result_line, "\n"); $result_output = substr($result_line, 0, $start_of_line) . "\n"; $result_line = substr($result_line, $start_of_line + 1); } else { // Condition $result_template_r[0] == $result_key[$i], include entire file since there is nothing to search pts_client::test_profile_debug_message('No Result Parsing Hint, Including Entire Result Output'); $result_line = trim($result_output); } pts_client::test_profile_debug_message('Result Line: ' . $result_line); $result_r = explode(' ', pts_strings::trim_spaces(str_replace($space_out_chars, ' ', str_replace('=', ' = ', $result_line)))); $result_r_pos = array_search($result_key[$i], $result_r); if(!empty($result_before_string[$i])) { // Using ResultBeforeString tag $result_before_this = array_search($result_before_string[$i], $result_r); if($result_before_this !== false) { array_push($test_results, $result_r[($result_before_this - 1)]); } } else if(isset($result_r[$result_template_r_pos])) { array_push($test_results, $result_r[$result_template_r_pos]); } } while($is_multi_match && count($test_results) != $result_count && !empty($result_output)); } foreach($test_results as $x => &$test_result) { if($strip_from_result[$i] != null) { $test_result = str_replace($strip_from_result[$i], null, $test_result); } if($strip_result_postfix[$i] != null && substr($test_result, 0 - strlen($strip_result_postfix[$i])) == $strip_result_postfix[$i]) { $test_result = substr($test_result, 0, 0 - strlen($strip_result_postfix[$i])); } // Expand validity checking here if($is_numeric_check == true && is_numeric($test_result) == false) { unset($test_results[$x]); continue; } if($result_divide_by[$i] != null && is_numeric($result_divide_by[$i]) && $result_divide_by[$i] != 0) { $test_result = $test_result / $result_divide_by[$i]; } if($result_multiply_by[$i] != null && is_numeric($result_multiply_by[$i]) && $result_multiply_by[$i] != 0) { $test_result = $test_result * $result_multiply_by[$i]; } } if(empty($test_results)) { continue; } switch($multi_match[$i]) { case 'REPORT_ALL': $test_result = implode(',', $test_results); break; case 'AVERAGE': default: $test_result = array_sum($test_results) / count($test_results); break; } if($test_result != false) { break; } } return $test_result; } } ?> phoronix-test-suite/pts-core/objects/pts_test_result_buffer_item.php0000644000175000017500000000447412157130724026341 0ustar michaelmichael. */ class pts_test_result_buffer_item { private $result_identifier; private $result_final; private $result_raw; private $result_json; private $result_min; private $result_max; public function __construct($identifier, $final, $raw = null, $json = null, $min_value = null, $max_value = null) { $this->result_identifier = $identifier; $this->result_final = $final; $this->result_raw = $raw; $this->result_min = $min_value; $this->result_max = $max_value; if($json && !is_array($json)) { $json = json_decode($json, true); } $this->result_json = $json; } public function reset_result_identifier($identifier) { $this->result_identifier = $identifier; } public function reset_result_value($value) { $this->result_final = $value; } public function reset_raw_value($value) { $this->result_raw = $value; } public function get_result_identifier() { return $this->result_identifier; } public function get_result_value() { return $this->result_final; } public function get_min_result_value() { return $this->result_min; } public function get_max_result_value() { return $this->result_max; } public function get_result_raw() { return $this->result_raw; } public function get_result_json() { return $this->result_json; } public function __toString() { return strtolower($this->get_result_identifier()); } public static function compare_value($a, $b) { $a = $a->get_result_value(); $b = $b->get_result_value(); if($a == $b) { return 0; } return $a < $b ? -1 : 1; } } ?> phoronix-test-suite/pts-core/objects/pts_render.php0000644000175000017500000010202412203755113022657 0ustar michaelmichael. */ class pts_render { public static function render_graph(&$result_object, &$result_file = null, $save_as = false, $extra_attributes = null) { $graph = self::render_graph_process($result_object, $result_file, $save_as, $extra_attributes); $graph->renderGraph(); return $graph->svg_dom->output($save_as); } public static function render_graph_inline_embed(&$object, &$result_file = null, $extra_attributes = null, $nested = true) { if($object instanceof pts_test_result) { $graph = self::render_graph_process($object, $result_file, false, $extra_attributes); } else if($object instanceof pts_Graph) { $graph = $object; } else { return false; } $graph->renderGraph(); $output_format = 'SVG'; $graph = $graph->svg_dom->output(null, $output_format); switch($output_format) { case 'PNG': case 'JPG': if($nested) { $graph = ''; } else { header('Content-Type: image/' . strtolower($output_format)); } break; default: case 'SVG': if($nested) { // strip out any DOCTYPE and other crud that would be redundant, so start at SVG tag $graph = substr($graph, strpos($graph, 'test_profile->get_display_format() == 'LINE_GRAPH' && $result_file->get_system_count() > 10) { // If there's too many lines being plotted on line graph, likely to look messy, so convert to scalar automatically $extra_attributes['compact_to_scalar'] = true; } // XXX: removed || $result_file->is_results_tracker() from below and should be added // Removing the command fixes cases like: 1210053-BY-MYRESULTS43 if($result_file->is_multi_way_comparison() || isset($extra_attributes['compact_to_scalar'])) { if((isset($extra_attributes['compact_to_scalar']) || (false && $result_file->is_multi_way_comparison())) && in_array($result_object->test_profile->get_display_format(), array('LINE_GRAPH', 'FILLED_LINE_GRAPH'))) { // Convert multi-way line graph into horizontal box plot if(false) { $result_object->test_profile->set_display_format('HORIZONTAL_BOX_PLOT'); } else { // Turn a multi-way line graph into an averaged bar graph $buffer_items = $result_object->test_result_buffer->get_buffer_items(); $result_object->test_result_buffer = new pts_test_result_buffer(); foreach($buffer_items as $buffer_item) { $values = pts_strings::comma_explode($buffer_item->get_result_value()); $avg_value = pts_math::set_precision(array_sum($values) / count($values), 2); $result_object->test_result_buffer->add_test_result($buffer_item->get_result_identifier(), $avg_value); } $result_object->test_profile->set_display_format('BAR_GRAPH'); } } if($result_object->test_profile->get_display_format() != 'PIE_CHART') { $result_table = false; pts_render::compact_result_file_test_object($result_object, $result_table, $result_file, $extra_attributes); } } else if(in_array($result_object->test_profile->get_display_format(), array('LINE_GRAPH', 'FILLED_LINE_GRAPH'))) { // Check to see for line graphs if every result is an array of the same result (i.e. a flat line for every result). // If all the results are just flat lines, you might as well convert it to a bar graph $buffer_items = $result_object->test_result_buffer->get_buffer_items(); $all_values_are_flat = false; $flat_values = array(); foreach($buffer_items as $i => $buffer_item) { $unique_in_buffer = array_unique(explode(',', $buffer_item->get_result_value())); $all_values_are_flat = count($unique_in_buffer) == 1; if($all_values_are_flat == false) { break; } $flat_values[$i] = array_pop($unique_in_buffer); } if($all_values_are_flat) { $result_object->test_result_buffer = new pts_test_result_buffer(); foreach($buffer_items as $i => $buffer_item) { $result_object->test_result_buffer->add_test_result($buffer_item->get_result_identifier(), $flat_values[$i]); } $result_object->test_profile->set_display_format('BAR_GRAPH'); } } } public static function render_graph_process(&$result_object, &$result_file = null, $save_as = false, $extra_attributes = null) { if(isset($extra_attributes['sort_result_buffer'])) { $result_object->test_result_buffer->sort_buffer_items(); } if(isset($extra_attributes['reverse_result_buffer'])) { $result_object->test_result_buffer->buffer_values_reverse(); } if(isset($extra_attributes['normalize_result_buffer'])) { if(isset($extra_attributes['highlight_graph_values']) && is_array($extra_attributes['highlight_graph_values']) && count($extra_attributes['highlight_graph_values']) == 1) { $normalize_against = $extra_attributes['highlight_graph_values'][0]; } else { $normalize_against = false; } $result_object->normalize_buffer_values($normalize_against); } if($result_file != null) { // Cache the redundant words on identifiers so it's not re-computed on every graph static $redundant_word_cache; if(!isset($redundant_word_cache[$result_file->get_title()])) { $redundant_word_cache[$result_file->get_title()] = pts_render::evaluate_redundant_identifier_words($result_file->get_system_identifiers()); } if($redundant_word_cache[$result_file->get_title()]) { $result_object->test_result_buffer->auto_shorten_buffer_identifiers($redundant_word_cache[$result_file->get_title()]); } } self::multi_way_compact($result_file, $result_object, $extra_attributes); $display_format = $result_object->test_profile->get_display_format(); $bar_orientation = 'HORIZONTAL'; // default to horizontal bar graph switch($display_format) { case 'LINE_GRAPH': if(false && $result_object->test_result_buffer->get_count() > 5) { // If there's too many lines close to each other, it's likely to look cluttered so turn it into horizontal range bar / box chart graph $display_format = 'HORIZONTAL_BOX_PLOT'; $graph = new pts_HorizontalBoxPlotGraph($result_object, $result_file); } else { $graph = new pts_LineGraph($result_object, $result_file); } break; case 'HORIZONTAL_BOX_PLOT': $graph = new pts_HorizontalBoxPlotGraph($result_object, $result_file); break; case 'BAR_ANALYZE_GRAPH': case 'BAR_GRAPH': if($bar_orientation == 'VERTICAL') { $graph = new pts_VerticalBarGraph($result_object, $result_file); } else { $graph = new pts_HorizontalBarGraph($result_object, $result_file); } break; case 'PASS_FAIL': $graph = new pts_PassFailGraph($result_object, $result_file); break; case 'MULTI_PASS_FAIL': $graph = new pts_MultiPassFailGraph($result_object, $result_file); break; case 'TEST_COUNT_PASS': $graph = new pts_TestCountPassGraph($result_object, $result_file); break; case 'PIE_CHART': $graph = new pts_PieChart($result_object, $result_file); break; case 'IMAGE_COMPARISON': $graph = new pts_ImageComparisonGraph($result_object, $result_file); break; case 'FILLED_LINE_GRAPH': $graph = new pts_FilledLineGraph($result_object, $result_file); break; case 'SCATTER_PLOT': $graph = new pts_ScatterPlot($result_object, $result_file); break; default: if(isset($extra_attributes['graph_render_type'])) { $requested_graph_type = $extra_attributes['graph_render_type']; } else if(defined('GRAPH_RENDER_TYPE')) { $requested_graph_type = GRAPH_RENDER_TYPE; } else { $requested_graph_type = null; } switch($requested_graph_type) { case 'CANDLESTICK': $graph = new pts_CandleStickGraph($result_object, $result_file); break; case 'LINE_GRAPH': $graph = new pts_LineGraph($result_object, $result_file); break; case 'FILLED_LINE_GRAPH': $graph = new pts_FilledLineGraph($result_object, $result_file); break; default: if($bar_orientation == 'VERTICAL') { $graph = new pts_VerticalBarGraph($result_object, $result_file); } else { $graph = new pts_HorizontalBarGraph($result_object, $result_file); } break; } break; } if(isset($extra_attributes['regression_marker_threshold'])) { $graph->markResultRegressions($extra_attributes['regression_marker_threshold']); } if(isset($extra_attributes['set_alternate_view'])) { $graph->setAlternateView($extra_attributes['set_alternate_view']); } if(isset($extra_attributes['sort_result_buffer_values'])) { $result_object->test_result_buffer->buffer_values_sort(); if($result_object->test_profile->get_result_proportion() == 'HIB') { $result_object->test_result_buffer->buffer_values_reverse(); } } if(isset($extra_attributes['highlight_graph_values'])) { $graph->highlight_values($extra_attributes['highlight_graph_values']); } else if(PTS_IS_CLIENT && pts_client::read_env('GRAPH_HIGHLIGHT') != false) { $graph->highlight_values(pts_strings::comma_explode(pts_client::read_env('GRAPH_HIGHLIGHT'))); } switch($display_format) { case 'LINE_GRAPH': if(isset($extra_attributes['no_overview_text']) && $graph instanceof pts_LineGraph) { $graph->plot_overview_text = false; } case 'FILLED_LINE_GRAPH': case 'BAR_ANALYZE_GRAPH': case 'SCATTER_PLOT': //$graph->hideGraphIdentifiers(); foreach($result_object->test_result_buffer->get_buffer_items() as $buffer_item) { $graph->loadGraphValues(pts_strings::comma_explode($buffer_item->get_result_value()), $buffer_item->get_result_identifier()); $graph->loadGraphRawValues(pts_strings::comma_explode($buffer_item->get_result_raw())); } $scale_special = $result_object->test_profile->get_result_scale_offset(); if(!empty($scale_special) && count(($ss = pts_strings::comma_explode($scale_special))) > 0) { $graph->loadGraphIdentifiers($ss); } break; case 'HORIZONTAL_BOX_PLOT': // TODO: should be able to load pts_test_result_buffer_item objects more cleanly into pts_Graph $identifiers = array(); $values = array(); foreach($result_object->test_result_buffer->get_buffer_items() as $buffer_item) { array_push($identifiers, $buffer_item->get_result_identifier()); array_push($values, pts_strings::comma_explode($buffer_item->get_result_value())); } $graph->loadGraphIdentifiers($identifiers); $graph->loadGraphValues($values); break; default: // TODO: should be able to load pts_test_result_buffer_item objects more cleanly into pts_Graph $identifiers = array(); $values = array(); $raw_values = array(); foreach($result_object->test_result_buffer->get_buffer_items() as $buffer_item) { array_push($identifiers, $buffer_item->get_result_identifier()); array_push($values, $buffer_item->get_result_value()); array_push($raw_values, $buffer_item->get_result_raw()); } $graph->loadGraphIdentifiers($identifiers); $graph->loadGraphValues($values); $graph->loadGraphRawValues($raw_values); break; } self::report_test_notes_to_graph($graph, $result_object); return $graph; } public static function report_system_notes_to_table(&$result_file, &$table) { $system_json = $result_file->get_system_json(); $identifiers = $result_file->get_system_identifiers(); $identifier_count = count($identifiers); $system_attributes = array(); foreach($system_json as $i => $json) { if(isset($json['kernel-parameters']) && $json['kernel-parameters'] != null) { $system_attributes['Kernel'][$identifiers[$i]] = $json['kernel-parameters']; } if(isset($json['environment-variables']) && $json['environment-variables'] != null) { $system_attributes['Environment'][$identifiers[$i]] = $json['environment-variables']; } if(isset($json['compiler-configuration']) && $json['compiler-configuration'] != null) { $system_attributes['Compiler'][$identifiers[$i]] = $json['compiler-configuration']; } if(isset($json['disk-scheduler']) && isset($json['disk-mount-options'])) { $system_attributes['Disk'][$identifiers[$i]] = $json['disk-scheduler'] . ' / ' . $json['disk-mount-options']; } if(isset($json['cpu-scaling-governor'])) { $system_attributes['Processor'][$identifiers[$i]] = 'Scaling Governor: ' . $json['cpu-scaling-governor']; } if(isset($json['graphics-2d-acceleration']) || isset($json['graphics-aa']) || isset($json['graphics-af'])) { $report = array(); foreach(array('graphics-2d-acceleration', 'graphics-aa', 'graphics-af') as $check) { if(isset($json[$check]) && !empty($json[$check])) { array_push($report, $json[$check]); } } $system_attributes['Graphics'][$identifiers[$i]] = implode(' - ' , $report); } if(isset($json['graphics-compute-cores'])) { $system_attributes['OpenCL'][$identifiers[$i]] = 'GPU Compute Cores: ' . $json['graphics-compute-cores']; } } if(isset($system_attributes['compiler']) && count($system_attributes['compiler']) == 1 && ($result_file->get_system_count() > 1 && ($intent = pts_result_file_analyzer::analyze_result_file_intent($result_file, $intent, true)) && isset($intent[0]) && is_array($intent[0]) && array_shift($intent[0]) == 'Compiler') == false) { // Only show compiler strings when it's meaningful (since they tend to be long strings) unset($system_attributes['compiler']); } foreach($system_attributes as $index_name => $attributes) { $unique_attribue_count = count(array_unique($attributes)); $section = $identifier_count > 1 ? ucwords($index_name) : null; switch($unique_attribue_count) { case 0: break; case 1: if($identifier_count == count($attributes)) { // So there is something for all of the test runs and it's all the same... $table->addTestNote(array_pop($attributes), null, $section); } else { // There is missing data for some test runs for this value so report the runs this is relevant to. $table->addTestNote(implode(', ', array_keys($attributes)) . ': ' . array_pop($attributes), null, $section); } break; default: foreach($attributes as $identifier => $configuration) { $table->addTestNote($identifier . ': ' . $configuration, null, $section); } break; } } } protected static function report_test_notes_to_graph(&$graph, &$result_object) { // do some magic here to report any test notes.... $json = array(); $unique_compiler_data = array(); foreach($result_object->test_result_buffer->get_buffer_items() as $buffer_item) { $result_json = $buffer_item->get_result_json(); if(!empty($result_json)) { $json[$buffer_item->get_result_identifier()] = $result_json; if(isset($result_json['compiler-options']) && !empty($result_json['compiler-options'])) { pts_arrays::unique_push($unique_compiler_data, $result_json['compiler-options']); } } // report against graph with $graph->addTestNote($note, $hover_title = null); } if(empty($json)) { // no JSON data being reported to look at... return false; } if(isset($unique_compiler_data[0]['compiler-type']) && isset($unique_compiler_data[0]['compiler'])) { $compiler_options_string = '(' . strtoupper($unique_compiler_data[0]['compiler-type']) . ') ' . $unique_compiler_data[0]['compiler'] . ' options: '; } else { $compiler_options_string = null; } switch(count($unique_compiler_data)) { case 0: break; case 1: if($unique_compiler_data[0]['compiler-options'] != null) { $graph->addTestNote($compiler_options_string . $unique_compiler_data[0]['compiler-options'], $unique_compiler_data[0]['compiler-options']); } break; default: $diff = call_user_func_array('array_diff', $unique_compiler_data); if(count($diff) == 1) { $key = array_keys($diff); $key = array_pop($key); } if(isset($key) && isset($diff[$key])) { $unique_compiler_data = array(); foreach($json as $identifier => &$data) { if(isset($data['compiler-options'][$key])) { $d = explode(' ', $data['compiler-options'][$key]); if(!in_array($d, $unique_compiler_data)) { $unique_compiler_data[$identifier] = $d; } } } if(empty($unique_compiler_data)) { break; } if($key == 'compiler-options') { $intersect = count($unique_compiler_data) == 1 ? reset($unique_compiler_data) : call_user_func_array('array_intersect', $unique_compiler_data); $graph->addTestNote($compiler_options_string . implode(' ', $intersect)); } if(count($unique_compiler_data) > 1) { foreach($json as $identifier => &$data) { if(isset($data['compiler-options'][$key])) { $options = explode(' ', $data['compiler-options'][$key]); $diff = implode(' ', array_diff($options, $intersect)); if($diff) { $graph->addGraphIdentifierNote($identifier, $diff); } } } } } break; } foreach($json as $identifier => &$data) { // TODO XXX: Ultimately merge this data into the SE +/- line... if(isset($data['min-result']) && isset($data['max-result'])) { $graph->addGraphIdentifierNote($identifier, 'MIN: ' . $data['min-result'] . ' / MAX: ' . $data['max-result']); } } } public static function evaluate_redundant_identifier_words($identifiers) { if(count($identifiers) < 4 || strpos(pts_arrays::first_element($identifiers), ':') !== false) { // Probably not worth shortening so few result identifiers return false; } // Breakup the an identifier into an array by spaces to be used for comparison $common_segments = explode(' ', pts_arrays::first_element($identifiers)); $common_segments_last = explode(' ', pts_arrays::last_element($identifiers)); if(!isset($common_segments_last[2]) || !isset($common_segments[2])) { // If there aren't at least three words in identifier, probably can't be shortened well return false; } foreach(array_reverse($identifiers) as $id) { $words = explode(' ', $id); foreach($words as $i => $word) { if(isset($common_segments[$i]) && $word != $common_segments[$i] && isset($word[2]) && !ctype_alnum(substr($word, -1))) { // IS COMMON WORD } else { unset($common_segments[$i]); } } if(count($common_segments) == 0) { return false; } } return $common_segments; } 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); $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; } public static function compact_result_file_test_object(&$mto, &$result_table = false, &$result_file, $extra_attributes = null) { $identifiers_inverted = $result_file && $result_file->is_multi_way_inverted(); // TODO: this may need to be cleaned up, its logic is rather messy $condense_multi_way = isset($extra_attributes['condense_multi_way']); if(count($mto->test_profile->get_result_scale_offset()) > 0) { // It's already doing something return; } $scale_special = array(); $days = array(); $systems = array(); $prev_date = null; $is_tracking = true; $sha1_short_count = 0; $buffer_count = $mto->test_result_buffer->get_count(); if($identifiers_inverted) { $system_index = 0; $date_index = 1; } else { $system_index = 1; $date_index = 0; } foreach($mto->test_result_buffer->get_buffer_items() as $buffer_item) { $identifier = array_map('trim', explode(':', $buffer_item->get_result_identifier())); switch(count($identifier)) { case 2: $system = $identifier[$system_index]; $date = $identifier[$date_index]; break; case 1: $system = 0; $date = $identifier[0]; break; default: return; break; } if(!isset($systems[$system])) { $systems[$system] = 0; } if(!isset($days[$date])) { $days[$date] = null; } if($is_tracking) { // First do a dirty SHA1 hash check if(strlen($date) != 40 || strpos($date, ' ') !== false) { if(($x = strpos($date, ' + ')) !== false) { $date = substr($date, 0, $x); } // Check to see if only numeric changes are being made $sha1_short_hash_ending = isset($date[7]) && ctype_alnum(substr($date, -8)); $date = str_replace('s', null, pts_strings::remove_from_string($date, pts_strings::CHAR_NUMERIC | pts_strings::CHAR_DASH | pts_strings::CHAR_DECIMAL)); if($sha1_short_hash_ending) { $sha1_short_count++; } if($prev_date != null && $date != $prev_date && $sha1_short_hash_ending == false && $sha1_short_count < 3) { $is_tracking = false; } $prev_date = $date; } } } if($is_tracking) { $prev_date_r = explode(' ', $prev_date); if(count($prev_date_r) == 2 && ctype_alpha($prev_date_r[0])) { // This check should make it so when like testing every Ubuntu releases (Ubuntu 11.04, Ubuntu 11.10, etc) it's not in a line graph $is_tracking = false; } } else if($is_tracking == false && $sha1_short_count > 5) { // It's probably actually tracking..... based upon Stefan's Wine 1.4 example on 15 March 2012 $is_tracking = true; } foreach(array_keys($days) as $day_key) { $days[$day_key] = $systems; } $raw_days = $days; $json_days = $days; foreach($mto->test_result_buffer->get_buffer_items() as $buffer_item) { $identifier = array_map('trim', explode(':', $buffer_item->get_result_identifier())); switch(count($identifier)) { case 2: $system = $identifier[$system_index]; $date = $identifier[$date_index]; break; case 1: $system = 0; $date = $identifier[0]; break; default: return; break; } $days[$date][$system] = $buffer_item->get_result_value(); $raw_days[$date][$system] = $buffer_item->get_result_raw(); $json_days[$date][$system] = $buffer_item->get_result_json(); if(!is_numeric($days[$date][$system])) { return; } } $mto->test_result_buffer = new pts_test_result_buffer(); $day_keys = array_keys($days); if($condense_multi_way) { $mto->set_used_arguments_description($mto->get_arguments_description() . ' | Composite Of: ' . implode(' - ', array_keys($days))); foreach(array_keys($systems) as $system_key) { $sum = 0; $count = 0; foreach($day_keys as $day_key) { $sum += $days[$day_key][$system_key]; $count++; } $mto->test_result_buffer->add_test_result($system_key, ($sum / $count)); } } else { $mto->test_profile->set_result_scale($mto->test_profile->get_result_scale() . ' | ' . implode(',', array_keys($days))); if($is_tracking && $buffer_count < 16 && $result_file && pts_result_file_analyzer::analyze_result_file_intent($result_file) == false) { // It can't be a tracker if the result file is comparing hardware/software, etc $is_tracking = false; } switch($mto->test_profile->get_display_format()) { //case 'HORIZONTAL_BOX_PLOT': // $mto->test_profile->set_display_format('HORIZONTAL_BOX_PLOT_MULTI'); // break; case 'SCATTER_PLOT'; break; default: $line_graph_type = isset($extra_attributes['filled_line_graph']) ? 'FILLED_LINE_GRAPH' : 'LINE_GRAPH'; $mto->test_profile->set_display_format((count($days) < 5 || ($is_tracking == false && !isset($extra_attributes['force_line_graph_compact'])) ? 'BAR_ANALYZE_GRAPH' : $line_graph_type)); break; } foreach(array_keys($systems) as $system_key) { $results = array(); $raw_results = array(); $json_results = array(); foreach($day_keys as $day_key) { array_push($results, $days[$day_key][$system_key]); array_push($raw_results, $raw_days[$day_key][$system_key]); pts_arrays::unique_push($json_results, $json_days[$day_key][$system_key]); } // TODO XXX: Make JSON data work for multi-way comparisons! if(count($json_results) == 1) { $json = array_shift($json_results); } else { $json = null; } $mto->test_result_buffer->add_test_result($system_key, implode(',', $results), implode(',', $raw_results), $json); } } if($result_table !== false) { foreach(array_keys($systems) as $system_key) { foreach($day_keys as $day_key) { if(!isset($result_table[$system_key][$day_key])) { $result_table[$system_key][$day_key] = array(); } array_push($result_table[$system_key][$day_key], $days[$day_key][$system_key], $raw_days[$day_key][$system_key]); } } } } public static function multi_way_identifier_check($identifiers, &$system_hardware = null, &$result_file = null) { /* Samples To Use For Testing: 1109026-LI-AMDRADEON57 */ $systems = array(); $targets = array(); $is_multi_way = true; $is_multi_way_inverted = false; $is_ordered = true; $prev_system = null; foreach($identifiers as $identifier) { $identifier_r = explode(':', $identifier); if(count($identifier_r) != 2 || (isset($identifier[14]) && $identifier[4] == '-' && $identifier[13] == ':')) { // the later check will fix 0000-00-00 00:00 as breaking into date return false; } if(false && $is_ordered && $prev_system != null && $prev_system != $identifier_r[0] && isset($systems[$identifier_r[0]])) { // The results aren't ordered $is_ordered = false; if($result_file == null) { return false; } } $prev_system = $identifier_r[0]; $systems[$identifier_r[0]] = !isset($systems[$identifier_r[0]]) ? 1 : $systems[$identifier_r[0]] + 1; $targets[$identifier_r[1]] = !isset($targets[$identifier_r[1]]) ? 1 : $targets[$identifier_r[1]] + 1; } if(false && $is_ordered == false && $is_multi_way) { // TODO: get the reordering code to work if($result_file instanceof pts_result_file) { // Reorder the result file $to_order = array(); sort($identifiers); foreach($identifiers as $identifier) { array_push($to_order, new pts_result_merge_select($result_file, $identifier)); } $ordered_xml = pts_merge::merge_test_results_array($to_order); $result_file = new pts_result_file($ordered_xml); $is_multi_way = true; } else { $is_multi_way = false; } } $is_multi_way_inverted = $is_multi_way && count($targets) > count($systems); /* if($is_multi_way) { if(count($systems) < 3 && count($systems) != count($targets)) { $is_multi_way = false; } } */ // TODO XXX: for now temporarily disable inverted multi-way check to decide how to rework it appropriately /* if($is_multi_way) { $targets_count = count($targets); $systems_count = count($systems); if($targets_count > $systems_count) { $is_multi_way_inverted = true; } else if(is_array($system_hardware)) { $hardware = array_unique($system_hardware); //$software = array_unique($system_software); if($targets_count != $systems_count && count($hardware) == $systems_count) { $is_multi_way_inverted = true; } else if(count($hardware) == ($targets_count * $systems_count)) { $is_multi_way_inverted = true; } } } */ // TODO: figure out what else is needed to reasonably determine if the result file is a multi-way comparison return $is_multi_way ? array($is_multi_way, $is_multi_way_inverted) : false; } public static function renderer_compatibility_check($user_agent) { $user_agent .= ' '; $selected_renderer = 'SVG'; // Yahoo Slurp, msnbot, and googlebot should always be served SVG so no problems there if(($p = strpos($user_agent, 'Gecko/')) !== false) { // Mozilla Gecko-based browser (Firefox, etc) $gecko_date = substr($user_agent, ($p + 6)); $gecko_date = substr($gecko_date, 0, 6); // Around Firefox 3.0 era is best // Firefox 2.0 mostly works except text might not show... // With Firefox 17.0 it's now Gecko/17.0 rather than a date... if(substr($gecko_date, 0, 3) == '200' && $gecko_date < 200702) { $selected_renderer = 'PNG'; } } else if(($p = strpos($user_agent, 'AppleWebKit/')) !== false && strpos($user_agent, 'Chrome/') === false) { // All modern versions of Chrome should work with SVG // Safari, Google Chrome, Google Chromium, etc // Any version of Chrome should be okay $webkit_ver = substr($user_agent, ($p + 12)); $webkit_ver = substr($webkit_ver, 0, strpos($webkit_ver, ' ')); // Webkit 532.2 534.6 (WebOS 3.0.2) on WebOS is buggy for SVG // iPhone OS is using 533 right now if($webkit_ver < 533 || strpos($user_agent, 'hpwOS') !== false) { $selected_renderer = 'PNG'; } if(($p = strpos($user_agent, 'Android ')) !== false) { $android_ver = substr($user_agent, ($p + 8), 3); // Android browser doesn't support SVG. // Google bug report 1376 for Android - http://code.google.com/p/android/issues/detail?id=1376 // Looks like it might work though in 3.0 Honeycomb if($android_ver < 3.0) { $selected_renderer = 'PNG'; } } } else if(($p = strpos($user_agent, 'Opera/')) !== false) { // Opera $ver = substr($user_agent, ($p + 6)); $ver = substr($ver, 0, strpos($ver, ' ')); // 9.27, 9.64 displays most everything okay if($ver < 9.27) { $selected_renderer = 'PNG'; } // text-alignment is still fucked as of 11.50/12.0 // With PTS4 and the bilde_svg_dom calls not using dominant-baseline, Opera support seems to be fine // $selected_renderer = 'PNG'; } else if(($p = strpos($user_agent, 'Epiphany/')) !== false) { // Older versions of Epiphany. Newer versions should report their Gecko or WebKit appropriately $ver = substr($user_agent, ($p + 9)); $ver = substr($ver, 0, 4); if($ver < 2.22) { $selected_renderer = 'PNG'; } } else if(($p = strpos($user_agent, 'KHTML/')) !== false) { // KDE Konqueror as of 4.7 is still broken for SVG $selected_renderer = 'PNG'; } else if(($p = strpos($user_agent, 'MSIE ')) !== false) { $ver = substr($user_agent, ($p + 5), 1); // Microsoft Internet Explorer 9.0 finally seems to do SVG right if($ver < 10 && $ver != 1) { $selected_renderer = 'PNG'; } } else if(strpos($user_agent, 'facebook') !== false) { // Facebook uses this string for its Like/Share crawler, so serve it a PNG so it can use it as an image $selected_renderer = 'PNG'; } return $selected_renderer; } } ?> phoronix-test-suite/pts-core/objects/pts_test_profile_writer.php0000644000175000017500000001576412171652036025515 0ustar michaelmichael. */ class pts_test_profile_writer { private $xml_writer = null; private $result_identifier = null; public function __construct($result_identifier = null, &$xml_writer = null) { $this->result_identifier = $result_identifier; if($xml_writer instanceof nye_XmlWriter) { $this->xml_writer = $xml_writer; } else { $this->xml_writer = new nye_XmlWriter(); } } public function get_xml() { return $this->xml_writer->getXML(); } public function save_xml($to_save) { return $this->xml_writer->saveXMLFile($to_save); } public function rebuild_test_profile($test_profile) { $test_profile->xml_parser->block_test_extension_support(); $this->add_test_information($test_profile->xml_parser); $this->add_test_data_section($test_profile->xml_parser); $this->add_test_settings($test_profile); } public function add_test_information(&$xml_reader) { $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestInformation/Title', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestInformation/AppVersion', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestInformation/Description', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestInformation/ResultScale', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestInformation/Proportion', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestInformation/ResultQuantifier', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestInformation/DisplayFormat', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestInformation/SubTitle', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestInformation/Executable', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestInformation/TimesToRun', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestInformation/IgnoreRuns', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestInformation/InstallationAgreement', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestInformation/PreInstallMessage', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestInformation/PostInstallMessage', $xml_reader); } public function add_test_data_section(&$xml_reader) { $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/Version', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/SupportedPlatforms', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/SoftwareType', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/TestType', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/License', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/Status', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/SupportedArchitectures', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/ExternalDependencies', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/Extends', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/RequiresRoot', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/EnvironmentSize', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/EnvironmentTestingSize', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/EstimatedTimePerRun', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/ProjectURL', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/RequiresCoreVersionMin', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/RequiresCoreVersionMax', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/InternalTags', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/Maintainer', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/AllowResultsSharing', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestProfile/AutoSaveResults', $xml_reader); } public function add_test_settings(&$test_profile) { $xml_reader = &$test_profile->xml_parser; $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestSettings/Default/Arguments', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestSettings/Default/PostArguments', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestSettings/Default/AllowCacheShare', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestSettings/Default/MinimumLength', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/TestSettings/Default/MaximumLength', $xml_reader); foreach($test_profile->get_test_option_objects(false) as $option) { $this->xml_writer->addXmlNode('PhoronixTestSuite/TestSettings/Option/DisplayName', $option->get_name()); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/TestSettings/Option/Identifier', $option->get_identifier()); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/TestSettings/Option/ArgumentPrefix', $option->get_option_prefix()); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/TestSettings/Option/ArgumentPostfix', $option->get_option_postfix()); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/TestSettings/Option/DefaultEntry', $option->get_option_default_raw()); foreach($option->get_options_array() as $item) { $this->xml_writer->addXmlNode('PhoronixTestSuite/TestSettings/Option/Menu/Entry/Name', $item[0]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/TestSettings/Option/Menu/Entry/Value', $item[1]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/TestSettings/Option/Menu/Entry/Message', $item[2]); } } } } ?> phoronix-test-suite/pts-core/objects/pts_types.php0000644000175000017500000001405512077616510022560 0ustar michaelmichael. */ class pts_types { public static function subsystem_targets() { return self::parse_xsd_types('TestType'); } public static function software_license_types() { return self::parse_xsd_types('License'); } public static function test_profile_state_types() { return self::parse_xsd_types('ProfileStatus'); } public static function test_profile_software_types() { return self::parse_xsd_types('SoftwareType'); } public static function test_profile_display_formats() { return self::parse_xsd_types('DisplayFormat'); } public static function test_profile_quantifiers() { return self::parse_xsd_types('ResultQuantifier'); } public static function operating_systems() { return array(array('Linux'), array('Solaris', 'Sun'), array('BSD', 'DragonFly'), array('MacOSX', 'Darwin'), array('Windows'), array('Hurd', 'GNU')); } public static function identifiers_to_test_profile_objects($identifiers, $include_extensions = false, $remove_duplicates = true, &$archive_unknown_objects = false) { $test_profiles = array(); foreach(pts_types::identifiers_to_objects($identifiers, $archive_unknown_objects) as $object) { if($object instanceof pts_test_profile) { array_push($test_profiles, $object); } else if($object instanceof pts_test_suite || $object instanceof pts_virtual_test_suite) { foreach($object->get_contained_test_profiles() as $test_profile) { array_push($test_profiles, $test_profile); } } else if($object instanceof pts_result_file) { foreach($object->get_contained_test_profiles() as $test_profile) { array_push($test_profiles, $test_profile); } } } if($include_extensions) { $extended_test_profiles = array(); for($i = 0; $i < count($test_profiles); $i++) { foreach(array_reverse($test_profiles[$i]->extended_test_profiles()) as $test_profile) { if(!in_array($test_profile, $extended_test_profiles)) { array_push($extended_test_profiles, $test_profile); } } array_push($extended_test_profiles, $test_profiles[$i]); } // We end up doing this swapping around so the extended test profiles always end up before the tests extending them $test_profiles = $extended_test_profiles; unset($extended_test_profiles); } if($remove_duplicates) { $test_profiles = array_unique($test_profiles); } return $test_profiles; } public static function identifiers_to_objects($identifiers, &$archive_unknown_objects = false) { // Provide an array containing the location(s) of all test(s) for the supplied object name $objects = array(); foreach(pts_arrays::to_array($identifiers) as $identifier_item) { if($identifier_item instanceof pts_test_profile || $identifier_item instanceof pts_test_suite || $identifier_item instanceof pts_result_file) { array_push($objects, $identifier_item); } else if(($tp_identifier = pts_test_profile::is_test_profile($identifier_item))) { // Object is a test array_push($objects, new pts_test_profile($tp_identifier)); } else if(pts_test_suite::is_suite($identifier_item)) { // Object is a suite array_push($objects, new pts_test_suite($identifier_item)); } else if(pts_result_file::is_test_result_file($identifier_item)) { // Object is a saved results file array_push($objects, new pts_result_file($identifier_item)); } else if(pts_openbenchmarking::is_openbenchmarking_result_id($identifier_item)) { // Object is an OpenBenchmarking.org result // Clone it locally so it's just handled like a pts_result_file $success = pts_openbenchmarking::clone_openbenchmarking_result($identifier_item); if($success) { array_push($objects, new pts_result_file($identifier_item)); } } else if(PTS_IS_CLIENT && pts_virtual_test_suite::is_virtual_suite($identifier_item)) { // Object is a virtual suite array_push($objects, new pts_virtual_test_suite($identifier_item)); } else if(is_array($archive_unknown_objects)) { // Unknown / nothing / broken array_push($archive_unknown_objects, $identifier_item); } } return $objects; } public static function identifier_to_object($identifier) { $return = pts_types::identifiers_to_objects($identifier); return isset($return[0]) ? $return[0] : false; } public static function is_result_file($identifier) { return pts_types::identifier_to_object($identifier) instanceof pts_result_file ? true : false; } public static function is_test_or_suite($identifier) { return pts_test_profile::is_test_profile($identifier) || pts_test_suite::is_suite($identifier); } private static function parse_xsd_types($type_name) { $values = array(); $dom = new DOMDocument(); $dom->load(PTS_OPENBENCHMARKING_PATH . 'schemas/types.xsd'); $types = $dom->getElementsByTagName('schema')->item(0)->getElementsByTagName('simpleType'); for($i = 0; $i < $types->length; $i++) { if($types->item($i)->attributes->getNamedItem('name')->nodeValue == $type_name) { $enumerations = $types->item($i)->getElementsByTagName('restriction')->item(0)->getElementsByTagName('enumeration'); for($j = 0; $j < $enumerations->length; $j++) { array_push($values, $enumerations->item($j)->attributes->getNamedItem('value')->nodeValue); } break; } } return $values; } } ?> phoronix-test-suite/pts-core/objects/pts_exdep_platform_parser.php0000664000175000017500000001031212222312152025756 0ustar michaelmichael. */ class pts_exdep_platform_parser { public $struct; public function __construct($identifier = null) { $this->struct = array('external-dependencies' => array('name' => null, 'package_manager' => null, 'aliases' => array(), 'packages' => array())); if(PTS_IS_CLIENT) { $xml = PTS_EXDEP_PATH . 'xml/' . $identifier . '-packages.xml'; $xml_parser = new nye_XmlReader($xml); $this->struct['external-dependencies']['name'] = $xml_parser->getXMLValue('PhoronixTestSuite/ExternalDependencies/Information/Name'); $this->struct['external-dependencies']['package_manager'] = $xml_parser->getXMLValue('PhoronixTestSuite/ExternalDependencies/Information/PackageManager'); $generic_package = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ExternalDependencies/Package/GenericName'); $distro_package = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ExternalDependencies/Package/PackageName'); $file_check = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ExternalDependencies/Package/FileCheck'); $arch_specific = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ExternalDependencies/Package/ArchitectureSpecific'); $os_version_specific = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ExternalDependencies/Package/VersionSpecific'); $os_version = phodevi::read_property('system', 'os-version'); foreach(array_keys($generic_package) as $i) { if(empty($generic_package[$i])) { continue; } $os_version_compliant = empty($os_version_specific[$i]) || in_array($os_version, pts_strings::comma_explode($os_version_specific[$i])); if($os_version_compliant == false) { continue; } $this->struct['external-dependencies']['packages'][$generic_package[$i]] = $this->get_package_format($distro_package[$i], $file_check[$i], $arch_specific[$i]); } $aliases = $xml_parser->getXMLValue('PhoronixTestSuite/ExternalDependencies/Information/Aliases'); if($aliases != null) { $aliases = pts_strings::trim_explode(',', $aliases); foreach($aliases as $alias) { if($alias != null) { array_push($this->struct['external-dependencies']['aliases'], $alias); } } } } } public function get_package_format($distro_package = null, $file_check = null, $arch_specific = null) { if(!is_array($arch_specific)) { $arch_specific = pts_strings::comma_explode($arch_specific); } return array( 'os_package' => $distro_package, 'file_check' => $file_check, 'arch_specific' => $arch_specific ); } public function get_name() { return $this->struct['external-dependencies']['name']; } public function get_package_manager() { return $this->struct['external-dependencies']['package_manager']; } public function get_aliases() { $aliases = $this->struct['external-dependencies']['aliases']; foreach($aliases as &$alias) { $alias = strtolower(str_replace(' ', null, $alias)); } return $aliases; } public function get_aliases_formatted() { return $this->struct['external-dependencies']['aliases']; } public function is_package($package) { return isset($this->struct['external-dependencies']['packages'][$package]); } public function get_available_packages() { return array_keys($this->struct['external-dependencies']['packages']); } public function get_package_data($package) { return $this->is_package($package) ? $this->struct['external-dependencies']['packages'][$package] : $this->get_package_format(); } } ?> phoronix-test-suite/pts-core/objects/pts_virtual_test_suite.php0000644000175000017500000002505312200342247025341 0ustar michaelmichael. */ class pts_virtual_test_suite { private $identifier; private $repo; private $virtual; private $is_virtual_os_selector = false; private $is_virtual_subsystem_selector = false; private $is_virtual_software_type = false; private $is_virtual_internal_tag = false; private $is_virtual_installed = false; public function __construct($identifier) { $this->identifier = $identifier; $identifier = explode('/', $identifier); $this->repo = $identifier[0]; $this->virtual = $identifier[1]; $this->is_virtual_os_selector = self::is_selector_os($identifier[1]); $this->is_virtual_subsystem_selector = self::is_selector_subsystem($identifier[1]); $this->is_virtual_software_type = self::is_selector_software_type($identifier[1]); $this->is_virtual_internal_tag = self::is_selector_internal_tag($this->repo, $this->virtual); $this->is_virtual_installed = ($this->virtual == 'installed'); } public function __toString() { return $this->identifier; } public static function available_virtual_suites() { $virtual_suites = array(); $possible_identifiers = array_merge( array('all', 'installed'), array_map('strtolower', self::available_operating_systems()), array_map('strtolower', pts_types::subsystem_targets()), array_map('strtolower', pts_types::test_profile_software_types()) ); foreach(pts_openbenchmarking::linked_repositories() as $repo) { $repo_identifiers = array_merge($possible_identifiers, self::tags_in_repo($repo)); foreach($repo_identifiers as $id) { $virt_suite = $repo . '/' . $id; if(self::is_virtual_suite($virt_suite)) { $virtual_suite = pts_types::identifier_to_object($virt_suite); if($virtual_suite instanceof pts_virtual_test_suite) { array_push($virtual_suites, $virtual_suite); } } } } return $virtual_suites; } public static function is_virtual_suite($identifier) { $identifier = explode('/', $identifier); $is_virtual_suite = false; if(count($identifier) == 2) { // read the repo pts_openbenchmarking::refresh_repository_lists(array($identifier[0])); $repo_index = pts_openbenchmarking::read_repository_index($identifier[0]); if(isset($repo_index['tests']) && is_array($repo_index['tests'])) { // figure out virtual suites if($identifier[1] == 'all') { // virtual suite of all supported tests $is_virtual_suite = true; } else if($identifier[1] == 'installed') { // virtual suite of all installed tests $is_virtual_suite = true; } else if(self::is_selector_os($identifier[1])) { // virtual suite of all supported tests by a given operating system $is_virtual_suite = true; } else if(self::is_selector_subsystem($identifier[1])) { // virtual suite of all supported tests by a given TestType / subsystem $is_virtual_suite = true; } else if(self::is_selector_software_type($identifier[1])) { // virtual suite of all supported tests by a given SoftwareType $is_virtual_suite = true; } else if(self::is_selector_internal_tag($identifier[0], $identifier[1])) { // virtual suite of all supported tests by a given SoftwareType $is_virtual_suite = true; } } } return $is_virtual_suite; } public function get_identifier() { return $this->identifier; } public function get_title() { if($this->is_virtual_os_selector) { $title = $this->is_virtual_os_selector . ' Operating System Tests'; } else if($this->is_virtual_subsystem_selector) { $title = $this->is_virtual_subsystem_selector . ' Subsystem Tests'; } else if($this->is_virtual_software_type) { $title = $this->is_virtual_software_type . ' Tests'; } else if($this->is_virtual_internal_tag) { $title = ucwords($this->is_virtual_internal_tag) . ' Tests'; } else if($this->is_virtual_installed) { $title = 'Installed Tests'; } else if(substr($this->identifier, strrpos($this->identifier, '/') + 1) == 'all') { $title = 'All ' . strtoupper(substr($this->identifier, 0, strpos($this->identifier, '/'))) . ' Tests'; } else { $title = 'Virtual Suite'; } return $title; } public function get_description() { if($this->is_virtual_os_selector) { $description = 'This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being compatible with the ' . $this->is_virtual_os_selector . ' Operating System.'; } else if($this->is_virtual_subsystem_selector) { $description = 'This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a test of the ' . $this->is_virtual_subsystem_selector . ' sub-system.'; } else if($this->is_virtual_software_type) { $description = 'This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a ' . $this->is_virtual_software_type . ' software test.'; } else if($this->is_virtual_internal_tag) { $description = 'This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified via an internal tag as testing ' . $this->is_virtual_internal_tag . '.'; } else if($this->is_virtual_installed) { $description = 'This is a collection of test profiles found within the specified OpenBenchmarking.org repository that are already installed on the system under test.'; } else if(substr($this->identifier, strrpos($this->identifier, '/') + 1) == 'all') { $description = 'This is a collection of all test profiles found within the specified OpenBenchmarking.org repository.'; } else { $description = 'Virtual Suite'; } return $description; } public function is_core_version_supported() { // It's virtual and created by pts-core so it's always supported return true; } private static function is_selector_os($id) { $yes = false; foreach(self::available_operating_systems() as $name => $os) { if($os === $id) { // virtual suite of all supported tests by a given operating system $yes = $name; break; } } return $yes; } private static function available_operating_systems() { $os = array(); foreach(pts_types::operating_systems() as $os_r) { $os[$os_r[0]] = strtolower($os_r[0]); } return $os; } private static function is_selector_subsystem($id) { $yes = false; foreach(pts_types::subsystem_targets() as $subsystem) { if(strtolower($subsystem) === $id) { // virtual suite of all supported tests by a given TestType / subsystem $yes = $subsystem; break; } } return $yes; } private static function is_selector_software_type($id) { $yes = false; foreach(pts_types::test_profile_software_types() as $subsystem) { if(strtolower($subsystem) === $id && $subsystem != 'BaseTestProfile') { // virtual suite of all supported tests by a given SoftwareType $yes = $subsystem; break; } } return $yes; } private static function is_selector_internal_tag($repo, $id) { $yes = false; if(($i = array_search(strtolower($id), self::tags_in_repo($repo))) !== false) { // virtual suite of all test profiles matching an internal tag $tags = self::tags_in_repo($repo); $yes = $tags[$i]; } return $yes; } public static function tags_in_repo($repo) { $tags = array(); // read the repo $repo_index = pts_openbenchmarking::read_repository_index($repo); if(isset($repo_index['tests']) && is_array($repo_index['tests'])) { foreach($repo_index['tests'] as &$test) { foreach($test['internal_tags'] as $tag) { $tags[$tag] = strtolower($tag); } } } return $tags; } public function get_contained_test_profiles() { $contained = array(); // read the repo $repo_index = pts_openbenchmarking::read_repository_index($this->repo); if(isset($repo_index['tests']) && is_array($repo_index['tests'])) { foreach($repo_index['tests'] as $test_identifier => &$test) { if(!in_array(phodevi::operating_system(), $test['supported_platforms']) || empty($test['title'])) { // Initial check to not do unsupported tests continue; } if($this->is_virtual_os_selector && !in_array($this->virtual, array_map('strtolower', $test['supported_platforms']))) { // Doing a virtual suite of all tests specific to an OS, but this test profile is not supported there continue; } else if($this->is_virtual_subsystem_selector && $this->virtual != strtolower($test['test_type'])) { // Doing a virtual suite of all tests specific to a test_type, but this test profile is not supported there continue; } else if($this->is_virtual_software_type && $this->virtual != strtolower($test['software_type'])) { // Doing a virtual suite of all tests specific to a software_type, but this test profile is not supported there continue; } else if($this->is_virtual_internal_tag && !in_array($this->virtual, array_map('strtolower', $test['internal_tags']))) { // Doing a virtual suite of all tests matching an internal tag continue; } $test_version = array_shift($test['versions']); $test_profile = new pts_test_profile($this->repo . '/' . $test_identifier . '-' . $test_version); if($test_profile->get_display_format() != 'BAR_GRAPH' || !in_array($test_profile->get_license(), array('Free', 'Non-Free'))) { // Also ignore these tests continue; } if($this->is_virtual_installed && $test_profile->is_test_installed() == false) { // Test is not installed continue; } if($test_profile->is_supported(false)) { // All checks passed, add to virtual suite array_push($contained, $test_profile); continue; } } } return $contained; } } ?> phoronix-test-suite/pts-core/objects/pts_test_profile_parser.php0000644000175000017500000002724212202504763025465 0ustar michaelmichael. */ class pts_test_profile_parser { protected $identifier; public $xml_parser; public function __construct($identifier = null) { if(strpos($identifier, '') === false) { $identifier = pts_openbenchmarking::evaluate_string_to_qualifier($identifier, true, 'test'); } $this->xml_parser = new pts_test_nye_XmlReader($identifier); if(!isset($identifier[64])) { // Passed is not an identifier since it's too long $this->identifier = $identifier; } } public function __toString() { return $this->get_identifier(); } public function __clone() { $this->xml_parser = clone $this->xml_parser; } public function get_identifier($bind_version = true) { $identifier = $this->identifier; if($bind_version == false && ($c = strrpos($identifier, '-'))) { if(pts_strings::is_version(substr($identifier, ($c + 1)))) { $identifier = substr($identifier, 0, $c); } } return "$identifier"; } public function get_maintainer() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/Maintainer'); } public function get_test_hardware_type() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/TestType'); } public function get_test_software_type() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/SoftwareType'); } public function get_status() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/Status'); } public function get_license() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/License'); } public function get_test_profile_version() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/Version'); } public function get_app_version() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/AppVersion'); } public function get_project_url() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/ProjectURL'); } public function get_description() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/Description'); } public function get_title() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/Title'); } public function get_dependencies() { return pts_strings::comma_explode($this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/ExternalDependencies')); } public function get_pre_install_message() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/PreInstallMessage'); } public function get_post_install_message() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/PostInstallMessage'); } public function get_installation_agreement_message() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/InstallationAgreement'); } public function get_internal_tags_raw() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/InternalTags'); } public function get_internal_tags() { return pts_strings::comma_explode($this->get_internal_tags_raw()); } public function get_default_arguments() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestSettings/Default/Arguments'); } public function get_default_post_arguments() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestSettings/Default/PostArguments'); } public function get_identifier_base_name() { $identifier = basename($this->identifier); if(($s = strrpos($identifier, '-')) !== false) { $post_dash = substr($identifier, ($s + 1)); // If the version is attached, remove it if(pts_strings::is_version($post_dash)) { $identifier = substr($identifier, 0, $s); } } return $identifier; } public function get_test_executable() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/Executable', $this->get_identifier_base_name()); } public function get_times_to_run() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/TimesToRun', 3); } public function get_runs_to_ignore() { return pts_strings::comma_explode($this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/IgnoreRuns')); } public function get_pre_run_message() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/PreRunMessage'); } public function get_post_run_message() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/PostRunMessage'); } public function get_result_scale() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/ResultScale'); } public function get_result_scale_formatted() { return trim(pts_strings::first_in_string($this->get_result_scale(), '|')); } public function get_result_scale_offset() { $scale_parts = explode('|', $this->get_result_scale()); return count($scale_parts) == 2 ? trim($scale_parts[1]) : array(); } public function get_result_proportion() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/Proportion'); } public function get_display_format() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/DisplayFormat', 'BAR_GRAPH'); } public function do_auto_save_results() { return pts_strings::string_bool($this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/AutoSaveResults', 'FALSE')); } public function get_result_quantifier() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/ResultQuantifier'); } public function is_root_required() { return pts_strings::string_bool($this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/RequiresRoot', 'FALSE')); } public function allow_cache_share() { return pts_strings::string_bool($this->xml_parser->getXMLValue('PhoronixTestSuite/TestSettings/Default/AllowCacheShare', 'FALSE')); } public function allow_results_sharing() { return pts_strings::string_bool($this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/AllowResultsSharing', 'TRUE')); } public function get_min_length() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestSettings/Default/MinimumLength'); } public function get_max_length() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestSettings/Default/MaximumLength'); } public function get_test_subtitle() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestInformation/SubTitle'); } public function get_supported_platforms_raw() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/SupportedPlatforms'); } public function get_supported_platforms() { return pts_strings::comma_explode($this->get_supported_platforms_raw()); } public function get_supported_architectures() { return pts_strings::comma_explode($this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/SupportedArchitectures')); } public function get_environment_size() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/EnvironmentSize', 0); } public function get_test_extension() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/Extends'); } public function get_environment_testing_size() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/EnvironmentTestingSize', 0); } public function get_estimated_run_time() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/EstimatedTimePerRun', 0) * $this->get_times_to_run(); } public function requires_core_version_min() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/RequiresCoreVersionMin', 2950); } public function requires_core_version_max() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/TestProfile/RequiresCoreVersionMax', 9190); } public function get_test_option_objects($auto_process = true) { $settings_name = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/TestSettings/Option/DisplayName'); $settings_argument_prefix = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/TestSettings/Option/ArgumentPrefix'); $settings_argument_postfix = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/TestSettings/Option/ArgumentPostfix'); $settings_identifier = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/TestSettings/Option/Identifier'); $settings_default = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/TestSettings/Option/DefaultEntry'); $option_names = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/TestSettings/Option/Menu/Entry/Name', 1); $option_messages = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/TestSettings/Option/Menu/Entry/Message', 1); $option_values = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/TestSettings/Option/Menu/Entry/Value', 1); $test_options = array(); foreach(array_keys($settings_name) as $option_count) { $names = $option_names[$option_count]; $messages = $option_messages[$option_count]; $values = $option_values[$option_count]; if($auto_process) { pts_test_run_options::auto_process_test_option($this->identifier, $settings_identifier[$option_count], $names, $values, $messages); } $user_option = new pts_test_option($settings_identifier[$option_count], $settings_name[$option_count]); $user_option->set_option_prefix($settings_argument_prefix[$option_count]); $user_option->set_option_postfix($settings_argument_postfix[$option_count]); for($i = 0; $i < count($names); $i++) { $user_option->add_option($names[$i], (isset($values[$i]) ? $values[$i] : null), (isset($messages[$i]) ? $messages[$i] : null)); } $user_option->set_option_default($settings_default[$option_count]); array_push($test_options, $user_option); } return $test_options; } public function get_reference_id() { // This isn't needed for test profiles, but keep this here for compatibility when passing a test_profile to pts_result_file_writer return null; } // // Set Functions // public function set_times_to_run($times) { $this->xml_parser->overrideXMLValue('PhoronixTestSuite/TestInformation/TimesToRun', $times); } public function set_result_scale($scale) { $this->xml_parser->overrideXMLValue('PhoronixTestSuite/TestInformation/ResultScale', $scale); } public function set_result_proportion($proportion) { $this->xml_parser->overrideXMLValue('PhoronixTestSuite/TestInformation/Proportion', $proportion); } public function set_display_format($format) { $this->xml_parser->overrideXMLValue('PhoronixTestSuite/TestInformation/DisplayFormat', $format); } public function set_result_quantifier($quantifier) { $this->xml_parser->overrideXMLValue('PhoronixTestSuite/TestInformation/ResultQuantifier', $quantifier); } public function set_version($version) { $this->xml_parser->overrideXMLValue('PhoronixTestSuite/TestInformation/AppVersion', $version); } public function set_test_title($title) { $this->xml_parser->overrideXMLValue('PhoronixTestSuite/TestInformation/Title', $title); } public function set_identifier($identifier) { $this->identifier = $identifier; } } ?> phoronix-test-suite/pts-core/objects/pts_svg_dom.php0000644000175000017500000002653512130644720023052 0ustar michaelmichael. */ class pts_svg_dom { protected $dom; protected $svg; protected $width; protected $height; public function __construct($width, $height) { $dom = new DOMImplementation(); $dtd = $dom->createDocumentType('svg', '-//W3C//DTD SVG 1.1//EN', 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'); $this->dom = $dom->createDocument(null, null, $dtd); $this->dom->formatOutput = PTS_IS_CLIENT; if(stripos(PTS_PHP_VERSION, 'hiphop') === false) { $pts_comment = $this->dom->createComment(pts_title(true) . ' [ http://www.phoronix-test-suite.com/ ]'); $this->dom->appendChild($pts_comment); } $this->svg = $this->dom->createElementNS('http://www.w3.org/2000/svg', 'svg'); $this->svg->setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); $this->svg->setAttribute('version', '1.1'); $this->svg->setAttribute('font-family', 'sans-serif'); $this->svg->setAttribute('viewbox', '0 0 ' . $width . ' ' . $height); $this->svg->setAttribute('width', $width); $this->svg->setAttribute('height', $height); $this->width = $width; $this->height = $height; $this->dom->appendChild($this->svg); } public function render_image($save_as = null, &$format = null) { // XXX: Alias for output. With PTS 3.8 this is just here for API compatibility with OpenBenchmarking.org. $this->output($save_as, $format); } public function output($save_as = null, &$format = null) { $output_format = 'SVG'; if(isset($_SERVER['HTTP_USER_AGENT']) || isset($_REQUEST['force_format'])) { static $browser_renderer = null; if(isset($_REQUEST['force_format'])) { // Don't nest the force_format within the browser_renderer null check in case its overriden by OpenBenchmarking.org dynamically $output_format = $_REQUEST['force_format']; } else if($browser_renderer == null) { $output_format = pts_render::renderer_compatibility_check($_SERVER['HTTP_USER_AGENT']); } else { $output_format = $browser_renderer; } } $format = $output_format; switch($output_format) { case 'JPEG': $output = pts_svg_dom_gd::svg_dom_to_gd($this->dom, 'JPEG'); $output_format = 'jpg'; break; case 'PNG': $output = pts_svg_dom_gd::svg_dom_to_gd($this->dom, 'PNG'); $output_format = 'png'; break; case 'SVG': default: $output = $this->save_xml(); $output_format = 'svg'; break; } if($output == null) { return false; } else if($save_as) { return file_put_contents(str_replace('BILDE_EXTENSION', $output_format, $save_as), $output); } else { return $output; } } public function save_xml() { return $this->dom->saveXML(); } public static function sanitize_hex($hex) { return $hex; // don't shorten it right now until the gd code can handle shortened hex codes $hex = preg_replace('/(?<=^#)([a-f0-9])\\1([a-f0-9])\\2([a-f0-9])\\3\z/i', '\1\2\3', $hex); return strtolower($hex); } public function draw_svg_line($start_x, $start_y, $end_x, $end_y, $color, $line_width = 1, $extra_elements = null) { $attributes = array('x1' => $start_x, 'y1' => $start_y, 'x2' => $end_x, 'y2' => $end_y, 'stroke' => $color, 'stroke-width' => $line_width); if($extra_elements != null) { $attributes = array_merge($attributes, $extra_elements); } $this->add_element('line', $attributes); } public function draw_svg_arc($center_x, $center_y, $radius, $offset_percent, $percent, $attributes) { $deg = ($percent * 360); $offset_deg = ($offset_percent * 360); $arc = $percent > 0.5 ? 1 : 0; $p1_x = round(cos(deg2rad($offset_deg)) * $radius) + $center_x; $p1_y = round(sin(deg2rad($offset_deg)) * $radius) + $center_y; $p2_x = round(cos(deg2rad($offset_deg + $deg)) * $radius) + $center_x; $p2_y = round(sin(deg2rad($offset_deg + $deg)) * $radius) + $center_y; $attributes['d'] = "M$center_x,$center_y L$p1_x,$p1_y A$radius,$radius 0 $arc,1 $p2_x,$p2_y Z"; $this->add_element('path', $attributes); } public function add_element($element_type, $attributes = array()) { $el = $this->dom->createElement($element_type); if(isset($attributes['xlink:href']) && $attributes['xlink:href'] != null && $element_type != 'a' && ($element_type != 'image' || (isset($attributes['http_link']) && $attributes['http_link'] != null))) { // image tag uses xlink:href as the image src, so check for 'http_link' instead to make a link out of it $link_key = ($element_type == 'image' ? 'http_link' : 'xlink:href'); $link = $this->dom->createElement('a'); $link->setAttribute('xlink:href', $attributes[$link_key]); $link->setAttribute('xlink:show', 'new'); $link->appendChild($el); $this->svg->appendChild($link); unset($attributes[$link_key]); } else { $this->svg->appendChild($el); } foreach($attributes as $name => $value) { $el->setAttribute($name, $value); } } public function add_text_element($text_string, $attributes) { $el = $this->dom->createElement('text'); $text_node = $this->dom->createTextNode($text_string); $el->appendChild($text_node); if(isset($attributes['xlink:href']) && $attributes['xlink:href'] != null) { $link = $this->dom->createElement('a'); $link->setAttribute('xlink:href', $attributes['xlink:href']); $link->setAttribute('xlink:show', 'new'); $link->appendChild($el); $this->svg->appendChild($link); unset($attributes['xlink:href']); } else { $this->svg->appendChild($el); } foreach($attributes as $name => $value) { if($value === null) { continue; } $el->setAttribute($name, $value); } } public function add_textarea_element($text_string, $attributes, &$estimated_height = 0) { if(!isset($attributes['width'])) { $attributes['width'] = $this->width - $attributes['x']; } $queue_dimensions = self::estimate_text_dimensions($text_string, $attributes['font-size']); if($queue_dimensions[0] < $attributes['width']) { // No wrapping is occuring, so stuff it in a more efficient text element instead $this->add_text_element($text_string, $attributes); $estimated_height += ($attributes['font-size'] + 3); return; } $el = $this->dom->createElement('text'); $word_queue = null; $line_count = 0; $words = explode(' ', $text_string); $word_count = count($words); $last_word = null; foreach($words as $i => $word) { $word_queue .= $word . ' '; $queue_dimensions = self::estimate_text_dimensions($word_queue, ($attributes['font-size'] - 0.45)); if($queue_dimensions[0] > $attributes['width'] || $i == ($word_count - 1)) { if($i != ($word_count - 1)) { $last_word_pos = strrpos($word_queue, ' ', -2); $last_word = substr($word_queue, $last_word_pos); $word_queue = substr($word_queue, 0, $last_word_pos); } $tspan = $this->dom->createElement('tspan'); $tspan->setAttribute('x', $attributes['x']); $tspan->setAttribute('y', $attributes['y']); $tspan->setAttribute('dx', ($line_count == 0 ? 0 : 5)); $tspan->setAttribute('dy', ($line_count * ($attributes['font-size'] + 1))); $text_node = $this->dom->createTextNode($word_queue); $tspan->appendChild($text_node); $el->appendChild($tspan); $word_queue = $last_word; $line_count++; } } $estimated_height += $line_count * ($attributes['font-size'] + 2); unset($attributes['width']); if(isset($attributes['xlink:href']) && $attributes['xlink:href'] != null) { $link = $this->dom->createElement('a'); $link->setAttribute('xlink:href', $attributes['xlink:href']); $link->setAttribute('xlink:show', 'new'); $link->appendChild($el); $this->svg->appendChild($link); unset($attributes['xlink:href']); } else { $this->svg->appendChild($el); } foreach($attributes as $name => $value) { $el->setAttribute($name, $value); } } public function draw_rectangle_gradient($x1, $y1, $width, $height, $color, $next_color) { static $gradient_count = 1; $gradient = $this->dom->createElement('linearGradient'); $gradient->setAttribute('id', 'g_' . $gradient_count); $gradient->setAttribute('x1', '0%'); $gradient->setAttribute('y1', '0%'); $gradient->setAttribute('x2', '100%'); $gradient->setAttribute('y2', '0%'); $stop = $this->dom->createElement('stop'); $stop->setAttribute('offset', '0%'); $stop->setAttribute('style', 'stop-color: ' . $color .'; stop-opacity: 1;'); $gradient->appendChild($stop); $stop = $this->dom->createElement('stop'); $stop->setAttribute('offset', '100%'); $stop->setAttribute('style', 'stop-color: ' . $next_color .'; stop-opacity: 1;'); $gradient->appendChild($stop); $defs = $this->dom->createElement('defs'); $defs->appendChild($gradient); $this->svg->appendChild($defs); $rect = $this->dom->createElement('rect'); $rect->setAttribute('x', $x1); $rect->setAttribute('y', $y1); $rect->setAttribute('width', $width); $rect->setAttribute('height', $height); //$rect->setAttribute('fill', $background_color); $rect->setAttribute('style', 'fill:url(#g_' . $gradient_count . ')'); $gradient_count++; $this->svg->appendChild($rect); } public static function html_embed_code($file_name, $file_type = 'SVG', $attributes = null, $is_xsl = false) { $attributes = pts_arrays::to_array($attributes); $file_name = str_replace('BILDE_EXTENSION', strtolower($file_type), $file_name); switch($file_type) { case 'SVG': $attributes['data'] = $file_name; if($is_xsl) { $html = ''; foreach($attributes as $option => $value) { $html .= '' . $value . ''; } $html .= ''; } else { $html = ' $value) { $html .= $option . '="' . $value . '" '; } $html .= '/>'; } break; default: $attributes['src'] = $file_name; if($is_xsl) { $html = ''; foreach($attributes as $option => $value) { $html .= '' . $value . ''; } $html .= ''; } else { $html = ' $value) { $html .= $option . '="' . $value . '" '; } $html .= '/>'; } break; } return $html; } public static function estimate_text_dimensions($text_string, $font_size) { $box_height = ceil(0.76 * $font_size); $box_width = ceil((0.76 * strlen($text_string) * $font_size) - ceil(strlen($text_string) * 1.05)); // Width x Height return array($box_width, $box_height); } public static function embed_png_image($png_img_file) { return 'data:image/png;base64,' . base64_encode(file_get_contents($png_img_file)); } } ?> phoronix-test-suite/pts-core/objects/pts_test_result_parser_writer.php0000644000175000017500000001403412171654722026740 0ustar michaelmichael. */ class pts_test_result_parser_writer { private $xml_writer = null; public function __construct() { $this->xml_writer = new nye_XmlWriter(); } public function get_xml() { return $this->xml_writer->getXML(); } public function save_xml($to_save) { return $this->xml_writer->saveXMLFile($to_save); } public function rebuild_parser_file($xml_file) { $xml_parser = new pts_parse_results_nye_XmlReader($xml_file); $result_template = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ResultsParser/OutputTemplate'); $result_match_test_arguments = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ResultsParser/MatchToTestArguments'); $result_key = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ResultsParser/ResultKey'); $result_line_hint = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ResultsParser/LineHint'); $result_line_before_hint = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ResultsParser/LineBeforeHint'); $result_line_after_hint = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ResultsParser/LineAfterHint'); $result_before_string = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ResultsParser/ResultBeforeString'); $strip_from_result = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ResultsParser/StripFromResult'); $strip_result_postfix = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ResultsParser/StripResultPostfix'); $multi_match = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ResultsParser/MultiMatch'); $result_divide_by = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ResultsParser/DivideResultBy'); $result_multiply_by = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ResultsParser/MultiplyResultBy'); foreach(array_keys($result_template) as $i) { $this->xml_writer->addXmlNode('PhoronixTestSuite/ResultsParser/OutputTemplate', $result_template[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ResultsParser/MatchToTestArguments', $result_match_test_arguments[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ResultsParser/ResultKey', $result_key[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ResultsParser/LineHint', $result_line_hint[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ResultsParser/LineBeforeHint', $result_line_before_hint[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ResultsParser/LineAfterHint', $result_line_after_hint[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ResultsParser/ResultBeforeString', $result_before_string[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ResultsParser/StripFromResult', $strip_from_result[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ResultsParser/StripResultPostfix', $strip_result_postfix[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ResultsParser/MultiMatch', $multi_match[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ResultsParser/DivideResultBy', $result_divide_by[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ResultsParser/MultiplyResultBy', $result_multiply_by[$i]); } $result_iqc_source_file = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ImageParser/SourceImage'); $result_match_test_arguments = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ImageParser/MatchToTestArguments'); $result_iqc_image_x = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ImageParser/ImageX'); $result_iqc_image_y = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ImageParser/ImageY'); $result_iqc_image_width = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ImageParser/ImageWidth'); $result_iqc_image_height = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ImageParser/ImageHeight'); foreach(array_keys($result_iqc_source_file) as $i) { $this->xml_writer->addXmlNode('PhoronixTestSuite/ImageParser/SourceImage', $result_iqc_source_file[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ImageParser/MatchToTestArguments', $result_match_test_arguments[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ImageParser/ImageX', $result_iqc_image_x[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ImageParser/ImageY', $result_iqc_image_y[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ImageParser/ImageWidth', $result_iqc_image_width[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/ImageParser/ImageHeight', $result_iqc_image_height[$i]); } $monitor_sensor = $xml_parser->getXMLArrayValues('PhoronixTestSuite/SystemMonitor/Sensor'); $monitor_frequency = $xml_parser->getXMLArrayValues('PhoronixTestSuite/SystemMonitor/PollingFrequency'); $monitor_report_as = $xml_parser->getXMLArrayValues('PhoronixTestSuite/SystemMonitor/Report'); foreach(array_keys($monitor_sensor) as $i) { $this->xml_writer->addXmlNode('PhoronixTestSuite/SystemMonitor/Sensor', $monitor_sensor[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/SystemMonitor/PollingFrequency', $monitor_frequency[$i]); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/SystemMonitor/Report', $monitor_report_as[$i]); } $extra_data_id = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ExtraData/Identifier'); foreach(array_keys($extra_data_id) as $i) { $this->xml_writer->addXmlNode('PhoronixTestSuite/ExtraData/Identifier', $extra_data_id[$i]); } } } ?> phoronix-test-suite/pts-core/objects/pts_strings.php0000644000175000017500000004154212157173102023100 0ustar michaelmichael. */ // TODO XXX: some of these functions may be better optimized using the ctype functions: http://us.php.net/manual/en/ref.ctype.php class pts_strings { const CHAR_LETTER = 2; const CHAR_NUMERIC = 4; const CHAR_DECIMAL = 8; const CHAR_SPACE = 16; const CHAR_DASH = 32; const CHAR_UNDERSCORE = 64; const CHAR_COLON = 128; const CHAR_COMMA = 256; const CHAR_SLASH = 512; const CHAR_AT = 1024; const CHAR_PLUS = 2048; const CHAR_SEMICOLON = 4096; const CHAR_EQUAL = 8192; public static function is_url($string) { $components = parse_url($string); return $components != false && isset($components['scheme']) && isset($components['host']); } public static function is_version($string) { // Only numeric or decimal, and at least a decimal (not int) return pts_strings::string_only_contains($string, (pts_strings::CHAR_NUMERIC | pts_strings::CHAR_DECIMAL)) && pts_strings::string_contains($string, pts_strings::CHAR_DECIMAL); } public static function trim_search_query($value) { $search_break_characters = array('@', '(', '/', '+', '[', '<', '/', '*', '"'); for($i = 0, $x = strlen($value); $i < $x; $i++) { if(in_array($value[$i], $search_break_characters)) { $value = substr($value, 0, $i); break; } } if((is_numeric($value) && substr($value, 0, 2) != '0x') || $value == null) { return; } // Remove multiplier if prepended to string $multiplier = strpos($value, ' x '); if($multiplier !== false && is_numeric(substr($value, 0, $multiplier))) { $value = substr($value, ($multiplier + 3)); } $value = str_replace('& ', null, $value); if(substr($value, -1) == '.') { $value = substr($value, 0, -1); } if(($w = stripos($value, 'WARNING')) !== false) { // to get rid of Scheisse like 'Gtk-WARNING **: Unable' $value = substr($value, 0, strrpos($value, ' ', (0 - (strlen($value) - $w)))); } // Remove other beginning or ending words based upon conditions $words = explode(' ', trim($value)); $c = count($words); switch($c) { case 1: if(isset($words[0][2]) && in_array(substr($words[0], -2), array('MB', 'GB', '0W'))) { // Just searching a disk / memory size or a power supply wattage $words = array(); } break; default: $last_index = ($c - 1); if(strpos($words[$last_index], 'v1') !== false || strpos($words[$last_index], 'MB') !== false || strpos($words[$last_index], 'GB') !== false) { // Version number being appended to product (some mobos) or the MB/GB size for GPUs array_pop($words); } else if(strpos($words[0], 'GB') !== false) { // Likely disk size in front of string array_shift($words); } break; } return implode(' ', $words); } public static function string_bool($string) { // Used for evaluating if the user inputted a string that evaluates to true return in_array(strtolower($string), array('true', '1')); } public static function add_trailing_slash($path) { if(PTS_IS_CLIENT && phodevi::is_windows() && strpos($path, ':\\') === 1) { return $path . (substr($path, -1) == '\\' ? null : '\\'); } else { return $path . (substr($path, -1) == '/' ? null : '/'); } } public static function trim_explode($delimiter, $to_explode) { return empty($to_explode) ? array() : array_map('trim', explode($delimiter, $to_explode)); } public static function comma_explode($to_explode) { return self::trim_explode(',', $to_explode); } public static function colon_explode($to_explode) { return self::trim_explode(':', $to_explode); } public static function first_in_string($string, $delimited_by = ' ') { return ($t = strpos($string, $delimited_by)) ? substr($string, 0, $t) : $string; } public static function last_in_string($string, $delimited_by = ' ') { return ($t = strrpos($string, $delimited_by)) ? substr($string, ($t + 1)) : $string; } public static function array_list_to_string($array, $bold_items = false, $append_to_end = null) { $count = count($array); if($bold_items) { foreach($array as &$item) { $item = '' . $item . ''; } } if($count > 1) { $temp = array_pop($array); array_push($array, 'and ' . $temp); } return implode(($count > 2 ? ', ' : ' ') . ' ', $array) . ($append_to_end != null ? ' ' . $append_to_end . ($count > 1 ? 's' : null) : null); } public static function has_in_string($string, $r) { $has_in_string = false; foreach($r as $string_to_check) { if(strpos($string, $string_to_check) !== false) { $has_in_string = $string_to_check; break; } } return $has_in_string; } public static function has_in_istring($string, $r) { $has_in_string = false; foreach($r as $string_to_check) { if(stripos($string, $string_to_check) !== false) { $has_in_string = $string_to_check; break; } } return $has_in_string; } public static function random_characters($length) { $random = null; for($i = 0; $i < $length; $i++) { $random .= chr(rand(65, 90)); } return $random; } public static function find_longest_string(&$string_r) { if(!is_array($string_r)) { return $string_r; } $longest_string = null; $longest_string_length = 0; foreach($string_r as $one_string) { if(is_array($one_string)) { $one_string = self::find_longest_string($one_string); } $one_string = strval($one_string); if(isset($one_string[$longest_string_length])) { $longest_string = $one_string; $longest_string_length = strlen($one_string); } } return $longest_string; } public static function char_is_of_type($char, $attributes) { $i = ord($char); if(($attributes & self::CHAR_LETTER) && (($i > 64 && $i < 91) || ($i > 96 && $i < 123))) { $is_of_type = true; } else if(($attributes & self::CHAR_NUMERIC) && $i > 47 && $i < 58) { $is_of_type = true; } else if(($attributes & self::CHAR_DECIMAL) && $i == 46) { $is_of_type = true; } else if(($attributes & self::CHAR_DASH) && $i == 45) { $is_of_type = true; } else if(($attributes & self::CHAR_UNDERSCORE) && $i == 95) { $is_of_type = true; } else if(($attributes & self::CHAR_COLON) && $i == 58) { $is_of_type = true; } else if(($attributes & self::CHAR_SPACE) && $i == 32) { $is_of_type = true; } else if(($attributes & self::CHAR_COMMA) && $i == 44) { $is_of_type = true; } else if(($attributes & self::CHAR_AT) && $i == 64) { $is_of_type = true; } else if(($attributes & self::CHAR_PLUS) && $i == 43) { $is_of_type = true; } else if(($attributes & self::CHAR_SEMICOLON) && $i == 59) { $is_of_type = true; } else if(($attributes & self::CHAR_EQUAL) && $i == 61) { $is_of_type = true; } else if(($attributes & self::CHAR_SLASH) && ($i == 47 || $i == 92)) { $is_of_type = true; } else { $is_of_type = false; } return $is_of_type; } public static function trim_spaces($str) { // get rid of multiple/redundant spaces that are next to each other $new_str = null; for($i = strlen($str); $i > 0; $i--) { // 32 is a ASCII space if(ord($str[($i - 1)]) != 32 || ($i < 2 || ord($str[($i - 2)]) != 32)) { $new_str = $str[$i - 1] . $new_str; } } return trim($new_str); } public static function remove_redundant($string, $redundant_char) { $prev_char = null; $new_string = null; for($i = 0, $l = strlen($string); $i < $l; $i++) { $this_char = $string[$i]; if($this_char != $redundant_char || $prev_char != $redundant_char) { $new_string .= $this_char; } $prev_char = $this_char; } return trim($new_string); } public static function strip_string($str) { // Clean a string containing hardware information of some common things to change/strip out $change_phrases = array( 'MCH' => 'Memory Controller Hub', 'AMD' => 'Advanced Micro Devices', 'MSI' => 'MICRO-STAR INTERNATIONAL', 'SiS' => 'Silicon Integrated Systems', 'Abit' => 'http://www.abit.com.tw/', 'ASUS' => 'ASUSTeK', 'HP' => 'Hewlett-Packard', 'NVIDIA' => 'nVidia', 'HDD' => 'HARDDISK', 'Intel' => 'Intel64', 'HD' => 'High Definition', 'IGP' => array('Integrated Graphics Controller', 'Express Graphics Controller', 'Integrated Graphics Device', 'Chipset Integrated') ); foreach($change_phrases as $new_phrase => $original_phrase) { $str = str_ireplace($original_phrase, $new_phrase, $str); } $remove_phrases = array('incorporation', 'corporation', 'corp.', 'invalid', 'technologies', 'technology', 'version', ' project ', 'computer', 'To Be Filled By', 'ODM', 'O.E.M.', 'Desktop Reference Platform', 'small form factor', 'convertible', ' group', 'chipset', 'community', 'reference', 'communications', 'semiconductor', 'processor', 'host bridge', 'adapter', ' CPU', 'platform', 'international', 'express', 'graphics', 'none', 'electronics', 'integrated', 'alternate', 'quad-core', 'memory', 'series', 'network', 'motherboard', 'electric ', 'industrial ', 'serverengines', 'Manufacturer', 'x86/mmx/sse2', '/AGP/SSE/3DNOW!', '/AGP/SSE2', 'controller', '(extreme graphics innovation)', 'pci-e_gfx and ht3 k8 part', 'pci-e_gfx and ht1 k8 part', 'Northbridge only', 'dual slot', 'dual-core', 'dual core', 'microsystems', 'not specified', 'single slot', 'genuine', 'unknown device', 'systemberatung', 'gmbh', 'graphics adapter', 'video device', 'http://', 'www.', '.com', '.tw/', '/pci/sse2/3dnow!', '/pcie/sse2', '/pci/sse2', 'balloon', 'network connection', 'ethernet', 'limited.', ' system', 'compliant', 'co. ltd', 'co.', 'ltd.', 'LTD ', ' LTD', '\AE', '(r)', '(tm)', 'inc.', 'inc', '6.00 PG', ',', '\'', '_ ', '_ ', 'corp', 'product name', 'base board', 'mainboard', 'pci to pci', ' release ', 'nee ', ' AG ', 'with Radeon HD'); $str = str_ireplace($remove_phrases, ' ', $str); if(($w = stripos($str, 'WARNING')) !== false) { // to get rid of Scheisse like 'Gtk-WARNING **: Unable' $str = substr($str, 0, strrpos($str, ' ', (0 - (strlen($str) - $w)))); } $str = pts_strings::trim_spaces($str); // Fixes an AMD string issue like 'FX -4100' due to stripping (TM) from in between characters, possibly other cases too $str = str_replace(' -', '-', $str); return $str; } public static function remove_line_timestamps($log) { // Try to strip out timestamps from lines like Xorg.0.log and dmesg, e.g.: // [ 326.390358] EXT4-fs (dm-1): initial error at 1306235400: ext4_journal_start_sb:251 $log = explode(PHP_EOL, $log); foreach($log as &$line) { if(substr($line, 0, 1) == '[' && ($t = strpos($line, '] ', 2)) !== false) { $encased_segment = trim(substr($line, 1, ($t - 1))); if(is_numeric($encased_segment)) { $line = substr($line, ($t + 2)); } } } $log = implode(PHP_EOL, $log); return $log; } public static function remove_lines_containing($contents, $contains) { foreach($contains as $needle) { while(($x = stripos($contents, $needle)) !== false) { $affected_line_begins = strrpos($contents, PHP_EOL, (0 - strlen($contents) + $x)); $affected_line_ends = strpos($contents, PHP_EOL, $x); $contents = substr($contents, 0, $affected_line_begins) . ($affected_line_ends === false ? null : substr($contents, $affected_line_ends)); } } return $contents; } public static function pts_version_to_codename($version) { $version = substr($version, 0, 3); $codenames = pts_version_codenames(); return isset($codenames[$version]) ? $codenames[$version] : null; } public static function parse_week_string($week_string, $delimiter = ' ') { $return_array = array(); foreach(array('S', 'M', 'T', 'W', 'TH', 'F', 'S') as $day_int => $day_char) { if($week_string[$day_int] == 1) { array_push($return_array, $day_char); } } return implode($delimiter, $return_array); } public static function remove_from_string($string, $attributes) { $string_r = str_split($string); $new_string = null; foreach($string_r as $char) { if(pts_strings::char_is_of_type($char, $attributes) == false) { $new_string .= $char; } } return $new_string; } public static function keep_in_string($string, $attributes) { $string_r = str_split($string); $new_string = null; foreach($string_r as $char) { if(pts_strings::char_is_of_type($char, $attributes) == true) { $new_string .= $char; } } return $new_string; } public static function string_only_contains($string, $attributes) { $string_r = str_split($string); foreach($string_r as $char) { if(pts_strings::char_is_of_type($char, $attributes) == false) { return false; } } return true; } public static function string_contains($string, $attributes) { $string_r = str_split($string); foreach($string_r as $char) { if(pts_strings::char_is_of_type($char, $attributes) == true) { return true; } } return false; } public static function times_occurred($string, $attributes) { $string_r = str_split($string); $times_matched = 0; foreach($string_r as $char) { if(pts_strings::char_is_of_type($char, $attributes) == true) { $times_matched++; } } return $times_matched; } public static function proximity_match($search, $match_to) { // Proximity search in $search string for * against $match_to $search = explode('*', $search); $is_match = true; if(count($search) == 1) { $is_match = false; } for($i = 0; $i < count($search) && $is_match && !empty($search[$i]); $i++) { if(($match_point = strpos($match_to, $search[$i])) !== false && ($i > 0 || $match_point == 0)) { $match_to = substr($match_to, ($match_point + strlen($search[$i]))); } else { $is_match = false; } } return $is_match; } public static function result_quantifier_to_string($quantifier) { $quantifiers = array('MAX' => 'Maximum', 'MIN' => 'Minimum', 'NULL' => null, 'AVG' => 'Average'); return isset($quantifiers[$quantifier]) ? $quantifiers[$quantifier] : 'Average'; } public static function format_time($time, $input_format = 'SECONDS', $standard_version = true, $round_to = 0) { switch($input_format) { case 'MINUTES': $time_in_seconds = $time * 60; break; case 'SECONDS': default: $time_in_seconds = $time; break; } if($round_to > 0) { $time_in_seconds += $round_to - ($time_in_seconds % $round_to); } $formatted_time = array(); if($time_in_seconds > 0) { $time_r = array(); $time_r[0] = array(floor($time_in_seconds / 3600), 'Hour'); $time_r[1] = array(floor(($time_in_seconds % 3600) / 60), 'Minute'); $time_r[2] = array($time_in_seconds % 60, 'Second'); foreach($time_r as $time_segment) { if($time_segment[0] > 0) { $formatted_part = $time_segment[0]; if($standard_version) { $formatted_part .= ' ' . $time_segment[1]; if($time_segment[0] > 1) { $formatted_part .= 's'; } } else { $formatted_part .= strtolower(substr($time_segment[1], 0, 1)); } array_push($formatted_time, $formatted_part); } } } return implode(($standard_version ? ', ' : null), $formatted_time); } public static function days_ago_format_string($days_ago) { if($days_ago < 30) { $days_ago .= ' day' . ($days_ago > 1 ? 's': null); } else { $days_ago = floor($days_ago / 30); if($days_ago >= 12) { $year = floor($days_ago / 12); $months = $days_ago % 12; $days_ago = $year . ' year' . ($year > 1 ? 's': null); if($months > 0) { $days_ago .= ', ' . $months . ' month' . ($months > 1 ? 's': null); } } else { $days_ago = $days_ago . ' month' . ($days_ago > 1 ? 's': null); } } return $days_ago; } public static function time_stamp_to_string($time_stamp, $string_type) { $stamp_half = explode(' ', trim($time_stamp)); $date = explode('-', $stamp_half[0]); $time = explode(':', (isset($stamp_half[1]) ? $stamp_half[1] : '00:00:00')); return date($string_type, mktime($time[0], $time[1], $time[2], $date[1], $date[2], $date[0])); } public static function system_category_to_openbenchmark_category($category) { $categories = array('Graphics' => 'GPU', 'Processor' => 'CPU', 'System' => 'CPU', 'File-System' => 'File System'); return isset($categories[$category]) ? $categories[$category] : $category; } } ?> phoronix-test-suite/pts-core/objects/pts_flags.php0000644000175000017500000001005312172340775022505 0ustar michaelmichael. */ pts_flags::init(); class pts_flags { private static $os_identifier_sha1 = null; private static $flags; // Flags private static $is_live_cd; private static $no_network_communication; private static $no_openbenchmarking_reporting; private static $user_agreement_skip; private static $skip_md5_checks; private static $remove_test_on_completion; private static $no_phodevi_cache; private static $no_external_dependencies; private static $upload_to_openbenchmarking; public static function init() { self::$flags = 0; self::$os_identifier_sha1 = sha1(phodevi::read_property('system', 'vendor-identifier')); self::$is_live_cd = (1 << 1); self::$no_network_communication = (1 << 2); self::$no_openbenchmarking_reporting = (1 << 3); self::$user_agreement_skip = (1 << 4); self::$skip_md5_checks = (1 << 5); self::$remove_test_on_completion = (1 << 6); self::$no_phodevi_cache = (1 << 7); self::$no_external_dependencies = (1 << 8); self::$upload_to_openbenchmarking = (1 << 9); switch(self::$os_identifier_sha1) { case 'b28d6a7148b34595c5b397dfcf5b12ac7932b3dc': // Moscow 2011-04 client self::$flags = self::$is_live_cd | self::$no_network_communication | self::$no_openbenchmarking_reporting | self::$user_agreement_skip | self::$skip_md5_checks | self::$remove_test_on_completion; break; } if(pts_client::read_env('NO_FILE_HASH_CHECKS') != false || pts_client::read_env('NO_MD5_CHECKS') != false) { self::$flags |= self::$skip_md5_checks; } if(pts_config::read_bool_config('PhoronixTestSuite/Options/Testing/RemoveTestInstallOnCompletion', 'FALSE')) { self::$flags |= self::$remove_test_on_completion; } if(pts_config::read_bool_config('PhoronixTestSuite/Options/Testing/AlwaysUploadResultsToOpenBenchmarking', 'FALSE')) { self::$flags |= self::$upload_to_openbenchmarking; } if(pts_client::read_env('NO_PHODEVI_CACHE') != false) { self::$flags |= self::$no_phodevi_cache; } if(pts_client::read_env('NO_EXTERNAL_DEPENDENCIES') != false || pts_client::read_env('SKIP_EXTERNAL_DEPENDENCIES') == 1) { // NO_EXTERNAL_DEPENDENCIES was deprecated in PTS 3.6 and replaced by more versatile SKIP_EXTERNAL_DEPENDENCIES self::$flags |= self::$no_external_dependencies; } } public static function os_identifier_hash() { return self::$os_identifier_sha1; } public static function is_live_cd() { return self::$flags & self::$is_live_cd; } public static function no_network_communication() { return self::$flags & self::$no_network_communication; } public static function no_openbenchmarking_reporting() { return self::$flags & self::$no_openbenchmarking_reporting; } public static function user_agreement_skip() { return self::$flags & self::$user_agreement_skip; } public static function skip_md5_checks() { return self::$flags & self::$skip_md5_checks; } public static function remove_test_on_completion() { return self::$flags & self::$remove_test_on_completion; } public static function no_phodevi_cache() { return self::$flags & self::$no_phodevi_cache; } public static function no_external_dependencies() { return self::$flags & self::$no_external_dependencies; } public static function upload_to_openbenchmarking() { return self::$flags & self::$upload_to_openbenchmarking; } } ?> phoronix-test-suite/pts-core/objects/pts_validation.php0000644000175000017500000001610112076635134023542 0ustar michaelmichael. */ class pts_validation { public static function process_libxml_errors() { $error_queue = array(); $errors = libxml_get_errors(); foreach($errors as $i => &$error) { if(isset($error_queue[$error->line])) { // There's already been an error reported for this line unset($errors[$i]); } switch($error->code) { case 1840: // Not in enumeration case 1839: // Not in pattern case 1871: // Missing / invalid element case 1833: // Below the minInclusive value echo PHP_EOL . $error->message; echo 'Line ' . $error->line . ': ' . $error->file . PHP_EOL; $error_queue[$error->line] = true; unset($errors[$i]); break; } } if(count($errors) > 0 && PTS_IS_CLIENT) { // DEBUG print_r($errors); } libxml_clear_errors(); } public static function test_profile_permitted_files() { $allowed_files = array('downloads.xml', 'test-definition.xml', 'results-definition.xml', 'install.sh', 'support-check.sh', 'pre.sh', 'post.sh', 'interim.sh', 'post-cache-share.sh'); foreach(pts_types::operating_systems() as $os) { $os = strtolower($os[0]); array_push($allowed_files, 'support-check_' . $os . '.sh'); array_push($allowed_files, 'install_' . $os . '.sh'); array_push($allowed_files, 'pre_' . $os . '.sh'); array_push($allowed_files, 'post_' . $os . '.sh'); array_push($allowed_files, 'interim_' . $os . '.sh'); } return $allowed_files; } public static function check_xml_tags(&$obj, &$tags_to_check, &$append_missing_to) { foreach($tags_to_check as $tag_check) { $to_check = $obj->xml_parser->getXMLValue($tag_check[0]); if(empty($to_check)) { array_push($append_missing_to, $tag_check); } } } public static function print_issue($type, $problems_r) { foreach($problems_r as $error) { list($target, $description) = $error; echo PHP_EOL . $type . ': ' . $description . PHP_EOL; if(!empty($target)) { echo 'TARGET: ' . $target . PHP_EOL; } } } public static function validate_test_suite(&$test_suite) { if($test_suite->xml_parser->getFileLocation() == null) { echo PHP_EOL . 'ERROR: The file location of the XML test suite source could not be determined.' . PHP_EOL; return false; } // Validate the XML against the XSD Schemas libxml_clear_errors(); // First rewrite the main XML file to ensure it is properly formatted, elements are ordered according to the schema, etc... $valid = $test_suite->xml_parser->validate(); if($valid == false) { echo PHP_EOL . 'Errors occurred parsing the main XML.' . PHP_EOL; pts_validation::process_libxml_errors(); return false; } else { echo PHP_EOL . 'Test Suite XML Is Valid.' . PHP_EOL; } return true; } public static function validate_test_profile(&$test_profile) { if($test_profile->xml_parser->getFileLocation() == null) { echo PHP_EOL . 'ERROR: The file location of the XML test profile source could not be determined.' . PHP_EOL; return false; } // Validate the XML against the XSD Schemas libxml_clear_errors(); // First rewrite the main XML file to ensure it is properly formatted, elements are ordered according to the schema, etc... $test_profile_writer = new pts_test_profile_writer(); $test_profile_writer->rebuild_test_profile($test_profile); $test_profile_writer->save_xml($test_profile->xml_parser->getFileLocation()); // Now re-create the pts_test_profile object around the rewritten XML $test_profile = new pts_test_profile($test_profile->get_identifier()); $valid = $test_profile->xml_parser->validate(); if($valid == false) { echo PHP_EOL . 'Errors occurred parsing the main XML.' . PHP_EOL; pts_validation::process_libxml_errors(); return false; } else { echo PHP_EOL . 'Test Profile XML Is Valid.' . PHP_EOL; } // Validate the downloads file $download_xml_file = $test_profile->get_file_download_spec(); if(empty($download_xml_file) == false) { $writer = new pts_test_profile_downloads_writer(); $writer->rebuild_download_file($test_profile); $writer->save_xml($download_xml_file); $downloads_parser = new pts_test_downloads_nye_XmlReader($download_xml_file); $valid = $downloads_parser->validate(); if($valid == false) { echo PHP_EOL . 'Errors occurred parsing the downloads XML.' . PHP_EOL; pts_validation::process_libxml_errors(); return false; } else { echo PHP_EOL . 'Test Downloads XML Is Valid.' . PHP_EOL; } // Validate the individual download files echo PHP_EOL . 'Testing File Download URLs.' . PHP_EOL; $files_missing = 0; $file_count = 0; foreach(pts_test_install_request::read_download_object_list($test_profile) as $download) { foreach($download->get_download_url_array() as $url) { $stream_context = pts_network::stream_context_create(); stream_context_set_params($stream_context, array('notification' => 'pts_stream_status_callback')); $file_pointer = fopen($url, 'r', false, $stream_context); if($file_pointer == false) { echo 'File Missing: ' . $download->get_filename() . ' / ' . $url . PHP_EOL; $files_missing++; } else { fclose($file_pointer); } $file_count++; } } if($files_missing > 0) // && $file_count == $files_missing { return false; } } // Validate the parser file $parser_file = $test_profile->get_file_parser_spec(); if(empty($parser_file) == false) { $writer = new pts_test_result_parser_writer(); $writer->rebuild_parser_file($parser_file); $writer->save_xml($parser_file); $parser = new pts_parse_results_nye_XmlReader($parser_file); $valid = $parser->validate(); if($valid == false) { echo PHP_EOL . 'Errors occurred parsing the results parser XML.' . PHP_EOL; pts_validation::process_libxml_errors(); return false; } else { echo PHP_EOL . 'Test Results Parser XML Is Valid.' . PHP_EOL; } } // Make sure no extra files are in there $allowed_files = pts_validation::test_profile_permitted_files(); foreach(pts_file_io::glob($test_profile->get_resource_dir() . '*') as $tp_file) { if(!is_file($tp_file) || !in_array(basename($tp_file), $allowed_files)) { echo PHP_EOL . basename($tp_file) . ' is not allowed in the test package.' . PHP_EOL; return false; } } return true; } } ?> phoronix-test-suite/pts-core/objects/pts_test_run_options.php0000644000175000017500000002776612120166563025044 0ustar michaelmichael. */ class pts_test_run_options { public static function prompt_user_options(&$test_profile, $preset_selections = null) { $user_args = array(); $text_args = array(); // Rather than using AUTO_TEST_OPTION_SELECTIONS, pass it to the $preset_selections argument if(($cli_presets_env = pts_client::read_env('PRESET_OPTIONS')) != false) { // To specify test options externally from an environment variable // i.e. PRESET_OPTIONS='stream.run-type=Add' ./phoronix-test-suite benchmark stream $preset_selections = pts_client::parse_value_string_double_identifier($cli_presets_env); } $identifier = $test_profile->get_identifier_base_name(); if(count($test_profile->get_test_option_objects()) > 0) { pts_client::$display->test_run_configure($test_profile); } foreach($test_profile->get_test_option_objects() as $i => $o) { $option_identifier = $o->get_identifier(); if($o->option_count() == 0) { // User inputs their option as there is nothing to select if(isset($preset_selections[$identifier][$option_identifier])) { $value = $preset_selections[$identifier][$option_identifier]; } else { echo PHP_EOL . $o->get_name() . PHP_EOL; $value = pts_user_io::prompt_user_input('Enter Value'); } array_push($text_args, array($o->format_option_display_from_input($value))); array_push($user_args, array($o->format_option_value_from_input($value))); } else { // Have the user select the desired option if(isset($preset_selections[$identifier][$option_identifier])) { $bench_choice = $preset_selections[$identifier][$option_identifier]; } else { $option_names = $o->get_all_option_names_with_messages(); if(count($option_names) > 1) { //echo PHP_EOL . $o->get_name() . ':' . PHP_EOL; array_push($option_names, 'Test All Options'); } $bench_choice = pts_user_io::prompt_text_menu($o->get_name(), $option_names, true, true, pts_client::$display->get_tab() . pts_client::$display->get_tab()); echo PHP_EOL; } $bench_choice = $o->parse_selection_choice_input($bench_choice); // Format the selected option(s) $option_args = array(); $option_args_description = array(); foreach($bench_choice as $c) { array_push($option_args, $o->format_option_value_from_select($c)); array_push($option_args_description, $o->format_option_display_from_select($c)); } array_push($text_args, $option_args_description); array_push($user_args, $option_args); } } $test_args = array(); $test_args_description = array(); self::compute_all_combinations($test_args, null, $user_args, 0); self::compute_all_combinations($test_args_description, null, $text_args, 0, ' - '); return array($test_args, $test_args_description); } public static function default_user_options(&$test_profile) { // Defaults mode for single test $all_args_real = array(); $all_args_description = array(); foreach($test_profile->get_test_option_objects() as $o) { $option_args = array(); $option_args_description = array(); $default_entry = $o->get_option_default(); if($o->option_count() == 2) { foreach(array(0, 1) as $i) { array_push($option_args, $o->format_option_value_from_select($i)); array_push($option_args_description, $o->format_option_display_from_select($i)); } } else { array_push($option_args, $o->format_option_value_from_select($default_entry)); array_push($option_args_description, $o->format_option_display_from_select($default_entry)); } array_push($all_args_real, $option_args); array_push($all_args_description, $option_args_description); } $test_args = array(); $test_args_description = array(); self::compute_all_combinations($test_args, null, $all_args_real, 0); self::compute_all_combinations($test_args_description, null, $all_args_description, 0, ' - '); return array($test_args, $test_args_description); } public static function batch_user_options(&$test_profile) { // Batch mode for single test $batch_all_args_real = array(); $batch_all_args_description = array(); foreach($test_profile->get_test_option_objects() as $o) { $option_args = array(); $option_args_description = array(); $option_count = $o->option_count(); for($i = 0; $i < $option_count; $i++) { array_push($option_args, $o->format_option_value_from_select($i)); array_push($option_args_description, $o->format_option_display_from_select($i)); } array_push($batch_all_args_real, $option_args); array_push($batch_all_args_description, $option_args_description); } $test_args = array(); $test_args_description = array(); self::compute_all_combinations($test_args, null, $batch_all_args_real, 0); self::compute_all_combinations($test_args_description, null, $batch_all_args_description, 0, ' - '); return array($test_args, $test_args_description); } protected static function compute_all_combinations(&$return_arr, $current_string, $options, $counter, $delimiter = ' ') { // In batch mode, find all possible combinations for test options if(count($options) <= $counter) { array_push($return_arr, trim($current_string)); } else { foreach($options[$counter] as $single_option) { $new_current_string = $current_string; if(!empty($new_current_string)) { $new_current_string .= $delimiter; } $new_current_string .= $single_option; self::compute_all_combinations($return_arr, $new_current_string, $options, $counter + 1, $delimiter); } } } public static function auto_process_test_option($test_identifier, $option_identifier, &$option_names, &$option_values, &$option_messages) { // Some test items have options that are dynamically built switch($option_identifier) { case 'auto-resolution': // Base options off available screen resolutions if(count($option_names) == 1 && count($option_values) == 1) { if(PTS_IS_CLIENT && pts_flags::is_live_cd()) { // Just use the stock resolution when operating from a LiveCD $available_video_modes = array(phodevi::read_property('gpu', 'screen-resolution')); } else if(PTS_IS_CLIENT && phodevi::read_property('gpu', 'screen-resolution') && phodevi::read_property('gpu', 'screen-resolution') != array(-1, -1)) { $available_video_modes = phodevi::read_property('gpu', 'available-modes'); } else { $available_video_modes = array(); } if(empty($available_video_modes)) { // Use hard-coded defaults $available_video_modes = array(array(800, 600), array(1024, 768), array(1280, 768), array(1280, 960), array(1280, 1024), array(1366, 768), array(1400, 1050), array(1600, 900), array(1680, 1050), array(1600, 1200), array(1920, 1080), array(2560, 1600)); } $format_name = $option_names[0]; $format_value = $option_values[0]; $option_names = array(); $option_values = array(); foreach($available_video_modes as $video_mode) { $this_name = str_replace('$VIDEO_WIDTH', $video_mode[0], $format_name); $this_name = str_replace('$VIDEO_HEIGHT', $video_mode[1], $this_name); $this_value = str_replace('$VIDEO_WIDTH', $video_mode[0], $format_value); $this_value = str_replace('$VIDEO_HEIGHT', $video_mode[1], $this_value); array_push($option_names, $this_name); array_push($option_values, $this_value); } } break; case 'auto-disk-partitions': case 'auto-disk-mount-points': // Base options off available disk partitions if(PTS_IS_CLIENT == false) { echo 'ERROR: This option is not supported in this configuration.'; return; } /*if(phodevi::is_linux()) { $all_devices = array_merge(pts_file_io::glob('/dev/hd*'), pts_file_io::glob('/dev/sd*')); } else if(phodevi::is_bsd()) { $all_devices = array_merge(pts_file_io::glob('/dev/ad*'), pts_file_io::glob('/dev/ada*')); } else { $all_devices = array(); }*/ $all_devices = array_merge(pts_file_io::glob('/dev/hd*'), pts_file_io::glob('/dev/sd*')); foreach($all_devices as &$device) { if(!is_numeric(substr($device, -1))) { unset($device); } } $option_values = array(); foreach($all_devices as $partition) { array_push($option_values, $partition); } if($option_identifier == 'auto-disk-mount-points') { $partitions_d = $option_values; $option_values = array(); $option_names = array(); $mounts = is_file('/proc/mounts') ? file_get_contents('/proc/mounts') : null; array_push($option_values, ''); array_push($option_names, 'Default Test Directory'); if(pts_flags::is_live_cd() == false) { foreach($partitions_d as $partition_d) { $mount_point = substr(($a = substr($mounts, strpos($mounts, $partition_d) + strlen($partition_d) + 1)), 0, strpos($a, ' ')); if(is_dir($mount_point) && is_writable($mount_point) && $mount_point != '/boot') { array_push($option_values, $mount_point); array_push($option_names, $mount_point . ' [' . $partition_d . ']'); } } } } else { $option_names = $option_values; } break; case 'auto-disks': // Base options off attached disks if(PTS_IS_CLIENT == false) { echo 'ERROR: This option is not supported in this configuration.'; return; } $all_devices = array_merge(pts_file_io::glob('/dev/hd*'), pts_file_io::glob('/dev/sd*')); foreach($all_devices as &$device) { if(is_numeric(substr($device, -1))) { unset($device); } } $option_values = array(); foreach($all_devices as $disk) { array_push($option_values, $disk); } $option_names = $option_values; break; case 'auto-removable-media': if(PTS_IS_CLIENT == false) { echo 'ERROR: This option is not supported in this configuration.'; return; } foreach(array_merge(pts_file_io::glob('/media/*/'), pts_file_io::glob('/Volumes/*/')) as $media_check) { if(is_dir($media_check) && is_writable($media_check)) // add more checks later on { array_push($option_names, $media_check); array_push($option_values, $media_check); } } break; case 'auto-file-select': if(PTS_IS_CLIENT == false) { echo 'ERROR: This option is not supported in this configuration.'; return; } $names = $option_names; $values = $option_values; $option_names = array(); $option_values = array(); for($i = 0; $i < count($names) && $i < count($values); $i++) { if(is_file($values[$i])) { array_push($option_names, $names[$i]); array_push($option_values, $values[$i]); } } break; case 'auto-directory-select': if(PTS_IS_CLIENT == false) { echo 'ERROR: This option is not supported in this configuration.'; return; } $names = $option_names; $values = $option_values; $option_names = array(); $option_values = array(); for($i = 0; $i < count($names) && $i < count($values); $i++) { if(is_dir($values[$i]) && is_writable($removable_media[$i])) { array_push($option_names, $names[$i]); array_push($option_values, $values[$i]); } } break; } } } ?> phoronix-test-suite/pts-core/objects/pts_test_suite.php0000644000175000017500000001437311754703056023612 0ustar michaelmichael. */ class pts_test_suite extends pts_test_suite_parser { public function __construct($identifier) { parent::__construct($identifier); } public static function is_suite($identifier) { $identifier = pts_openbenchmarking::evaluate_string_to_qualifier($identifier, true, 'suite'); return is_file(PTS_TEST_SUITE_PATH . $identifier . '/suite-definition.xml'); } public function needs_updated_install() { foreach(pts_types::identifiers_to_test_profile_objects($this->get_identifier(), false, true) as $test_profile) { if($test_profile->test_installation == false || $test_profile->test_installation->get_installed_system_identifier() != phodevi::system_id_string() || (pts_c::$test_flags & pts_c::force_install)) { return true; } } return false; } public function is_supported($report_warnings = false) { $supported_size = $original_size = count($this->get_contained_test_profiles()); foreach(pts_types::identifiers_to_test_profile_objects($this->identifier, false, true) as $test_profile) { if($test_profile->is_supported($report_warnings) == false) { $supported_size--; } } if($supported_size == 0) { $return_code = 0; } else if($supported_size != $original_size) { $return_code = 1; } else { $return_code = 2; } return $return_code; } public function get_unique_test_count() { return count(pts_types::identifiers_to_test_profile_objects($this->identifier, false, true)); } public function get_contained_test_result_objects() { $test_result_objects = array(); $test_names = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Execute/Test'); $sub_modes = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Execute/Mode'); $sub_arguments = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Execute/Arguments'); $sub_arguments_description = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Execute/Description'); $override_test_options = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Execute/OverrideTestOptions'); for($i = 0; $i < count($test_names); $i++) { $obj = pts_types::identifier_to_object($test_names[$i]); if($obj instanceof pts_test_profile) { // Check for test profile values to override $override_options = array(); if(!empty($override_test_options[$i])) { foreach(explode(';', $override_test_options[$i]) as $override_string) { $override_segments = pts_strings::trim_explode('=', $override_string); if(count($override_segments) == 2 && !empty($override_segments[0]) && !empty($override_segments[1])) { $override_options[$override_segments[0]] = $override_segments[1]; } } } switch($sub_modes[$i]) { case 'BATCH': $option_output = pts_test_run_options::batch_user_options($obj); break; case 'DEFAULTS': $option_output = pts_test_run_options::default_user_options($obj); break; default: $option_output = array(array($sub_arguments[$i]), array($sub_arguments_description[$i])); break; } foreach(array_keys($option_output[0]) as $x) { if($override_options != null) { $test_profile->set_override_values($override_options); } $test_result = new pts_test_result($obj); $test_result->set_used_arguments($option_output[0][$x]); $test_result->set_used_arguments_description($option_output[1][$x]); array_push($test_result_objects, $test_result); } } else if($obj instanceof pts_test_suite) { foreach($obj->get_contained_test_result_objects() as $test_result) { array_push($test_result_objects, $test_result); } } } return $test_result_objects; } public function pts_format_contained_tests_string() { $str = null; $this->pts_print_format_tests($this->identifier, $str); return $str; } public function is_core_version_supported() { // Check if the test suite's version is compatible with pts-core $core_version_min = parent::requires_core_version_min(); $core_version_max = parent::requires_core_version_max(); return $core_version_min <= PTS_CORE_VERSION && $core_version_max > PTS_CORE_VERSION; } public function pts_print_format_tests($object, &$write_buffer, $steps = -1) { // Print out a text tree that shows the suites and tests within an object $steps++; if(pts_test_suite::is_suite($object)) { $xml_parser = new pts_suite_nye_XmlReader($object); $test_names = array_unique($xml_parser->getXMLArrayValues('PhoronixTestSuite/Execute/Test')); if($steps > 0) { asort($test_names); } if($steps == 0) { $write_buffer .= $object . PHP_EOL; } else { $write_buffer .= str_repeat(' ', $steps) . '+ ' . $object . PHP_EOL; } foreach($test_names as $test) { $write_buffer .= $this->pts_print_format_tests($test, $write_buffer, $steps); } } else { $write_buffer .= str_repeat(' ', $steps) . '* ' . $object . PHP_EOL; } } public static function pts_format_tests_to_array($object) { // Print out a text tree that shows the suites and tests within an object $contained = array(); if(pts_test_suite::is_suite($object)) { $xml_parser = new pts_suite_nye_XmlReader($object); $test_names = array_unique($xml_parser->getXMLArrayValues('PhoronixTestSuite/Execute/Test')); $contained[$object] = array(); foreach($test_names as $test) { array_push($contained[$object], self::pts_format_tests_to_array($test)); } } else { $contained = $object; } return $contained; } } ?> phoronix-test-suite/pts-core/objects/pts_arrays.php0000644000175000017500000000335611727445634022727 0ustar michaelmichael. */ class pts_arrays { public static function first_element($array) { // Using this helper function will avoid a PHP E_STRICT warning if just using the code directly from the output of a function/object return reset($array); } public static function last_element($array) { // Using this helper function will avoid a PHP E_STRICT warning if just using the code directly from the output of a function/object return end($array); } public static function unique_push(&$array, $to_push) { // Only push to the array if it's a unique value return !in_array($to_push, $array) && array_push($array, $to_push); } public static function to_array($var) { return !is_array($var) ? array($var) : $var; } public static function json_encode_pretty_string($json) { return str_replace(array(',"', '{', '}'), array(",\n\t\"", " {\n\t", "\n}"), json_encode($json)); } public static function json_decode($str) { return json_decode($str, true); } } ?> phoronix-test-suite/pts-core/objects/pts_math.php0000644000175000017500000000565111627222615022346 0ustar michaelmichael. */ class pts_math { public static function geometric_mean($values) { return pow(array_product($values), (1 / count($values))); } public static function harmonic_mean($values) { $b = 0; $c = 0; foreach($values as $value) { if($value != 0) { $b += 1 / $value; $c++; } } return $b != 0 ? $c / $b : 0; } public static function standard_error($values) { self::clean_numeric_array($values); return empty($values) ? 0 : (self::standard_deviation($values) / sqrt(count($values))); } public static function standard_deviation($values) { self::clean_numeric_array($values); $count = count($values); if($count < 2) { return 0; } $total = array_sum($values); $mean = $total / $count; $standard_sum = 0; foreach($values as $value) { $standard_sum += pow(($value - $mean), 2); } return sqrt($standard_sum / ($count - 1)); } 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 static function set_precision($number, $precision = 2) { // This is better than using round() with precision because of the $precision is > than the current value, 0s will not be appended return number_format($number, $precision, '.', ''); } public static function find_percentile($values, $quartile) { sort($values, SORT_NUMERIC); $qr_index = count($values) * $quartile; $qr = $values[floor($qr_index)]; return $qr; } public static function first_quartile($values) { return self::find_percentile($values, 0.25); } public static function third_quartile($values) { return self::find_percentile($values, 0.75); } public static function inter_quartile_range($values) { return self::third_quartile($values) - self::first_quartile($values); } protected static function clean_numeric_array(&$values) { foreach($values as $i => $value) { if(!is_numeric($value)) { unset($values[$i]); } } } } ?> phoronix-test-suite/pts-core/objects/pts_html_template.php0000644000175000017500000000633511564763640024264 0ustar michaelmichael. */ class pts_html_template { private $dom; private $dom_body; private $section_list; public function __construct($Title = '', $SubTitle = '') { $this->dom = new DOMDocument(); $html = $this->dom->createElement('html'); $this->dom->appendChild($html); $head = $this->dom->createElement('head'); $title = $this->dom->createElement('title', $Title . ($SubTitle != null ? ' - ' . $SubTitle : null)); $head->appendChild($title); $html->appendChild($head); $this->dom_body = $this->dom->createElement('body'); $html->appendChild($this->dom_body); $p = $this->dom->createElement('h1', 'Phoronix Test Suite'); $this->dom_body->appendChild($p); $p = $this->dom->createElement('hr'); $p->setAttribute('style', 'height: 50px; border: 0;'); $this->dom_body->appendChild($p); $this->section_list = $this->dom->createElement('ol'); $this->dom_body->appendChild($this->section_list); } public function html_to_html($html) { $dom = new DOMDocument(); if(is_file($html)) { $dom->loadHTMLFile($html); } else { $dom->loadHTML($html); } $section_title = $dom->getElementsByTagName('html')->item(0)->getElementsByTagName('head')->item(0)->nodeValue; $section_li_a = $this->dom->createElement('a', $section_title); $section_li_a->setAttribute('href', '#' . str_replace(' ', null, $section_title)); $section_li = $this->dom->createElement('li'); $section_li->appendChild($section_li_a); $this->section_list->appendChild($section_li); $p = $this->dom->createElement('hr'); $p->setAttribute('style', 'height: 50px; border: 0;'); $this->dom_body->appendChild($p); $p = $this->dom->createElement('a'); $p->setAttribute('name', str_replace(' ', null, $section_title)); $this->dom_body->appendChild($p); $p = $this->dom->createElement('h1', $section_title); $this->dom_body->appendChild($p); // TODO: the below code is known to emit a fatal error right now since the nodes are different, need to copy/merge nodes between docs foreach($dom->getElementsByTagName('html')->item(0)->getElementsByTagName('body')->item(0)->childNodes as $node) { $n = $this->dom->importNode($node, true); $this->dom_body->appendChild($n); } } public function Output($File) { $p = $this->dom->createElement('p', 'Copyright © 2008 - ' . date('Y') . ' by Phoronix Media.'); $p->setAttribute('style', 'padding-top: 30px; text-align: center;'); $this->dom_body->appendChild($p); return $this->dom->saveHTMLFile($File); } } ?> phoronix-test-suite/pts-core/objects/pts_web.php0000644000175000017500000000150211705611443022157 0ustar michaelmichael. */ class pts_web { } ?> phoronix-test-suite/pts-core/objects/pts_result_file_analyze_manager.php0000644000175000017500000001317611712464454027154 0ustar michaelmichael. */ class pts_result_file_analyze_manager { private $test_results; private $relations; public function __construct() { $this->test_results = array(); $this->relations = array(); } public function add_test_result_set($test_object_array) { foreach($test_object_array as $mto) { $this->add_test_result($mto); } } public function add_test_result($mto) { $total_objects = count($this->test_results); $this->test_results[$total_objects] = $mto; $attributes = array_reverse(explode(' - ', $mto->get_arguments_description())); $attributes_clean = array(); for($i = 0; $i < count($attributes); $i++) { $temp = pts_strings::colon_explode($attributes[$i]); $attributes_clean[$temp[0]] = isset($temp[1]) ? $temp[1] : null; } if(!isset($this->relations[$mto->test_profile->get_identifier()][$mto->test_profile->get_test_profile_version()])) { $this->relations[$mto->test_profile->get_identifier()][$mto->test_profile->get_test_profile_version()] = array(); } array_push($this->relations[$mto->test_profile->get_identifier()][$mto->test_profile->get_test_profile_version()], array($total_objects, $attributes_clean)); } public function get_results() { $return_results = array(); $compared_to_index = array(); foreach($this->relations as $test_name => $tests_of_same_name) { foreach($tests_of_same_name as $test_version => $tests_of_same_name_and_version) { if(count($tests_of_same_name_and_version) == 1) { // Stub, no similar results to analyze array_push($return_results, $this->test_results[$tests_of_same_name_and_version[0][0]]); } else if(in_array($this->test_results[$tests_of_same_name_and_version[0][0]]->test_profile->get_display_format(), array('IMAGE_COMPARISON', 'LINE_GRAPH'))) { foreach($tests_of_same_name_and_version as $add) { array_push($return_results, $this->test_results[$add[0]]); } } else { foreach($tests_of_same_name_and_version as $test_info) { $similar_ids = array($test_info[0]); $similar_ids_names = array(); $diff_index = null; $this_attributes = $test_info[1]; foreach($tests_of_same_name_and_version as $compare_to) { if(in_array($compare_to[0], $similar_ids)) { continue; } $diff = array_diff_assoc($this_attributes, $compare_to[1]); if(count($diff) == 1) { if($diff_index == null) { $this_index = pts_arrays::last_element(array_keys($diff)); //$this_index_value = $diff[$this_index]; $index_id = implode(',', array($test_name, $test_version, $this_index)); if(in_array($index_id, $compared_to_index)) { continue; } array_push($compared_to_index, $index_id); array_push($similar_ids_names, $this_attributes[$this_index]); $diff_index = $this_index; } if(isset($diff[$diff_index])) { array_push($similar_ids, $compare_to[0]); array_push($similar_ids_names, $compare_to[1][$diff_index]); } } } if(count($similar_ids) > 1) { $mto = $this->test_results[$similar_ids[0]]; $results = array(); foreach($mto->test_result_buffer->get_identifiers() as $identifier) { $results[$identifier] = array(); } foreach($similar_ids as $id) { $mto_read = $this->test_results[$id]; $mto_identifiers = $mto_read->test_result_buffer->get_identifiers(); $mto_values = $mto_read->test_result_buffer->get_values(); foreach(array_keys($results) as $key) { for($i = 0; $i < count($mto_identifiers); $i++) { if($mto_identifiers[$i] == $key) { array_push($results[$key], $mto_values[$i]); break; } } } } $mto->test_result_buffer = new pts_test_result_buffer(); $do_line_graph = true; foreach($similar_ids_names as $id_name_check) { if(str_ireplace(array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'x', 'M', 'K', 'B', ' '), null, $id_name_check) != null) { $do_line_graph = false; break; } } if($do_line_graph && count($similar_ids_names) < 4) { $do_line_graph = false; } $mto->test_profile->set_display_format(($do_line_graph ? 'LINE_GRAPH' : 'BAR_ANALYZE_GRAPH')); $mto->set_used_arguments_description($diff_index . ' Analysis'); $mto->test_profile->set_result_scale($mto->test_profile->get_result_scale() . ' | ' . implode(',', $similar_ids_names)); foreach($results as $identifier => $values) { $mto->test_result_buffer->add_test_result($identifier, implode(',', $values), null); } array_push($return_results, $mto); } } } } } return $return_results; } } ?> phoronix-test-suite/pts-core/objects/pts_result_file_output.php0000644000175000017500000000432711713747155025360 0ustar michaelmichael. */ class pts_result_file_output { public static function result_file_to_csv(&$result_file) { $csv_output = null; $delimiter = ','; $csv_output .= $result_file->get_title() . PHP_EOL . PHP_EOL; $columns = $result_file->get_system_identifiers(); $rows = array(); $table_data = array(); pts_result_file_analyzer::system_components_to_table($table_data, $columns, $rows, $result_file->get_system_hardware()); pts_result_file_analyzer::system_components_to_table($table_data, $columns, $rows, $result_file->get_system_software()); $csv_output .= ' '; foreach($columns as $column) { $csv_output .= $delimiter . '"' . $column . '"'; } $csv_output .= PHP_EOL; foreach($rows as $i => $row) { $csv_output .= $row; foreach($columns as $column) { $csv_output .= $delimiter . $table_data[$column][$i]; } $csv_output .= PHP_EOL; } $csv_output .= PHP_EOL; $csv_output .= ' '; foreach($columns as $column) { $csv_output .= $delimiter . '"' . $column . '"'; } $csv_output .= PHP_EOL; foreach($result_file->get_result_objects() as $result_object) { $csv_output .= '"' . $result_object->test_profile->get_title() . ' - ' . $result_object->get_arguments_description() . '"'; foreach($result_object->test_result_buffer->get_values() as $value) { $csv_output .= $delimiter . $value; } $csv_output .= PHP_EOL; } $csv_output .= PHP_EOL; return $csv_output; } } ?> phoronix-test-suite/pts-core/objects/pts_test_suite_writer.php0000644000175000017500000001127711564533734025211 0ustar michaelmichael. */ class pts_test_suite_writer { private $xml_writer = null; private $result_identifier = null; public function __construct($result_identifier = null, &$xml_writer = null) { $this->result_identifier = $result_identifier; if($xml_writer instanceof nye_XmlWriter) { $this->xml_writer = $xml_writer; } else { $this->xml_writer = new nye_XmlWriter(); } } public function get_xml() { return $this->xml_writer->getXML(); } public function save_xml($to_save) { return $this->xml_writer->saveXMLFile($to_save); } public function add_suite_information_from_reader(&$xml_reader) { $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/SuiteInformation/Title', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/SuiteInformation/Version', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/SuiteInformation/TestType', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/SuiteInformation/Description', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/SuiteInformation/Maintainer', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/SuiteInformation/PreRunMessage', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/SuiteInformation/PostRunMessage', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/SuiteInformation/RunMode', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/SuiteInformation/RequiresCoreVersionMin', $xml_reader); $this->xml_writer->addXmlNodeFromReaderWNE('PhoronixTestSuite/SuiteInformation/RequiresCoreVersionMax', $xml_reader); } public function add_suite_information($name, $version, $maintainer, $type, $description) { $this->xml_writer->addXmlNode('PhoronixTestSuite/SuiteInformation/Title', $name); $this->xml_writer->addXmlNode('PhoronixTestSuite/SuiteInformation/Version', $version); $this->xml_writer->addXmlNode('PhoronixTestSuite/SuiteInformation/TestType', $type); $this->xml_writer->addXmlNode('PhoronixTestSuite/SuiteInformation/Description', $description); $this->xml_writer->addXmlNode('PhoronixTestSuite/SuiteInformation/Maintainer', $maintainer); } public function add_to_suite_from_reader(&$xml_reader) { $test_names = $xml_reader->getXMLArrayValues('PhoronixTestSuite/Execute/Test'); $sub_arguments = $xml_reader->getXMLArrayValues('PhoronixTestSuite/Execute/Arguments'); $sub_arguments_description = $xml_reader->getXMLArrayValues('PhoronixTestSuite/Execute/Description'); $sub_modes = $xml_reader->getXMLArrayValues('PhoronixTestSuite/Execute/Mode'); $override_test_options = $xml_reader->getXMLArrayValues('PhoronixTestSuite/Execute/OverrideTestOptions'); for($i = 0; $i < count($test_names); $i++) { $identifier = pts_openbenchmarking::evaluate_string_to_qualifier($test_names[$i]); if(empty($identifier)) { echo PHP_EOL . $test_names[$i] . ' fails.' . PHP_EOL; exit; } $identifier = substr($identifier, 0, strrpos($identifier, '-')); // strip the version for now $this->add_to_suite($identifier, $sub_arguments[$i], $sub_arguments_description[$i], $sub_modes[$i], $override_test_options[$i]); } } public function add_to_suite($identifier, $arguments, $description, $mode = null, $override = null) { $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Execute/Test', $identifier); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Execute/Arguments', $arguments); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Execute/Description', $description); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Execute/Mode', $mode); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Execute/OverrideTestOptions', $override); } public function add_to_suite_from_result_object(&$r_o) { $this->add_to_suite($r_o->test_profile->get_identifier(), $r_o->get_arguments(), $r_o->get_arguments_description()); } } ?> phoronix-test-suite/pts-core/objects/pts_test_result_buffer_extra.php0000644000175000017500000001104511713745623026525 0ustar michaelmichael. */ class pts_test_result_buffer_extra { public static function append_to_test_result(&$buffer_items, $identifier, $value) { if(($key = array_search(strtolower($identifier), $buffer_items)) !== false) { $buffer = $buffer_items[$key]; unset($buffer_items[$key]); $buffer_item = new pts_test_result_buffer_item($identifier, ($value + $buffer->get_result_value())); } else { $buffer_item = new pts_test_result_buffer_item($identifier, $value, null); } array_push($buffer_items, $buffer_item); } public static function clear_outlier_results(&$buffer_items, $add_to_other = true, $value_below = false) { $other_value = 0; foreach($buffer_items as $key => &$buffer_item) { if($value_below !== false && $buffer_item->get_result_value() < $value_below) { $other_value += $buffer_item->get_result_value(); unset($buffer_items[$key]); } } if($add_to_other && $other_value > 0) { self::append_to_test_result($buffer_items, 'Other', $other_value); } } public static function add_composite_result(&$test_result_buffer, $force = false) { $is_multi_way = $force ? $force : pts_render::multi_way_identifier_check($test_result_buffer->get_identifiers()); if($is_multi_way) { $group_values = array(); foreach($test_result_buffer->buffer_items as &$buffer_item) { $identifier_r = pts_strings::trim_explode(': ', $buffer_item->get_result_identifier()); if(!isset($group_values[$identifier_r[1]])) { $group_values[$identifier_r[1]] = 0; } $group_values[$identifier_r[1]] += $buffer_item->get_result_value(); } foreach($group_values as $key => $value) { if(1 == 0) { $title = $key . ': Composite'; } else { $title = 'Composite: ' . $key; } $test_result_buffer->add_test_result($title, $value); } } else { $total_value = array_sum($test_result_buffer->get_values()); $test_result_buffer->add_test_result('Composite', $total_value); } } public static function clear_iqr_outlier_results(&$test_result_buffer) { $is_multi_way = pts_render::multi_way_identifier_check($test_result_buffer->get_identifiers()); if($is_multi_way) { $group_values = array(); $group_keys = array(); foreach($test_result_buffer->buffer_items as $key => &$buffer_item) { $identifier_r = pts_strings::trim_explode(': ', $buffer_item->get_result_identifier()); if(!isset($group_values[$identifier_r[1]])) { $group_values[$identifier_r[1]] = array(); $group_keys[$identifier_r[1]] = array(); } array_push($group_values[$identifier_r[1]], $buffer_item->get_result_value()); array_push($group_keys[$identifier_r[1]], $key); } foreach($group_values as $group_key => $values) { // From: http://www.mathwords.com/o/outlier.htm $fqr = pts_math::first_quartile($values); $tqr = pts_math::third_quartile($values); $iqr_cut = ($tqr - $fqr) * 1.5; $bottom_cut = $fqr - $iqr_cut; $top_cut = $tqr + $iqr_cut; foreach($group_keys[$group_key] as $key) { $value = $test_result_buffer->buffer_items[$key]->get_result_value(); if($value > $top_cut || $value < $bottom_cut) { unset($test_result_buffer->buffer_items[$key]); } } } } else { // From: http://www.mathwords.com/o/outlier.htm $values = $test_result_buffer->get_values(); $fqr = pts_math::first_quartile($values); $tqr = pts_math::third_quartile($values); $iqr_cut = ($tqr - $fqr) * 1.5; $bottom_cut = $fqr - $iqr_cut; $top_cut = $tqr + $iqr_cut; foreach($test_result_buffer->buffer_items as $key => &$buffer_item) { $value = $buffer_item->get_result_value(); if($value > $top_cut || $value < $bottom_cut) { unset($test_result_buffer->buffer_items[$key]); } } } } } ?> phoronix-test-suite/pts-core/objects/pts_compression.php0000644000175000017500000001133711712460620023747 0ustar michaelmichael. */ class pts_compression { public static function compress_to_archive($to_compress, $compress_to) { $compress_to_file = basename($compress_to); $compress_base_dir = dirname($to_compress); $compress_base_name = basename($to_compress); switch(substr($compress_to_file, strpos($compress_to_file, '.') + 1)) { case 'tar': $extract_cmd = 'tar -cf ' . $compress_to . ' ' . $compress_base_name; break; case 'tar.gz': $extract_cmd = 'tar -czf ' . $compress_to . ' ' . $compress_base_name; break; case 'tar.bz2': $extract_cmd = 'tar -cjf ' . $compress_to . ' ' . $compress_base_name; break; case 'zip': $extract_cmd = 'zip -r ' . $compress_to . ' ' . $compress_base_name; break; default: $extract_cmd = null; break; } if($extract_cmd != null) { shell_exec('cd ' . $compress_base_dir . ' && ' . $extract_cmd . ' 2>&1'); } } public static function archive_extract($file) { $file_name = basename($file); $file_path = dirname($file); switch(substr($file_name, strpos($file_name, '.') + 1)) { case 'tar': $extract_cmd = 'tar -xf'; break; case 'tar.gz': $extract_cmd = 'tar -zxf'; break; case 'tar.bz2': $extract_cmd = 'tar -jxf'; break; case 'zip': $extract_cmd = 'unzip -o'; break; default: return false; } shell_exec('cd ' . $file_path . ' && ' . $extract_cmd . ' ' . $file_name . ' 2>&1'); return true; } public static function zip_archive_extract($zip_file, $extract_to) { $success = false; if(!is_readable($zip_file) || !is_writable($extract_to)) { return $success; } if(class_exists('ZipArchive')) { $zip = new ZipArchive(); if($zip->open($zip_file) === true) { $t = $zip->extractTo($extract_to); $zip->close(); $success = $t; } } else if(function_exists('zip_open')) { // the old PHP Zip API, but this is what webOS Optware uses and others $zip = zip_open($zip_file); if($zip) { while($zip_entry = zip_read($zip)) { $fp = fopen($extract_to . '/' . zip_entry_name($zip_entry), 'w'); if(zip_entry_open($zip, $zip_entry, 'r')) { $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry)); fwrite($fp, $buf); zip_entry_close($zip_entry); fclose($fp); } } zip_close($zip); $success = true; } } else { // Fallback to using external unzip command if(pts_client::executable_in_path('unzip')) { shell_exec('unzip -o ' . $zip_file . ' -d ' . $extract_to . ' 2>&1'); $success = true; } } return $success; } public static function zip_archive_create($zip_file, $add_files) { if(!class_exists('ZipArchive')) { return false; } $zip = new ZipArchive(); if($zip->open($zip_file, ZIPARCHIVE::CREATE) !== true) { $success = false; } else { foreach(pts_arrays::to_array($add_files) as $add_file) { self::zip_archive_add($zip, $add_file, dirname($add_file)); } $success = true; } return $success; } protected static function zip_archive_add(&$zip, $add_file, $base_dir = null) { if(is_dir($add_file)) { $zip->addEmptyDir(substr($add_file, strlen(pts_strings::add_trailing_slash($base_dir)))); foreach(pts_file_io::glob(pts_strings::add_trailing_slash($add_file) . '*') as $new_file) { self::zip_archive_add($zip, $new_file, $base_dir); } } else if(is_file($add_file)) { $zip->addFile($add_file, substr($add_file, strlen(pts_strings::add_trailing_slash($base_dir)))); } } public static function zip_archive_read_all_files($zip_file) { if(!class_exists('ZipArchive') || !is_readable($zip_file)) { return false; } $zip = new ZipArchive(); if($zip->open($zip_file) === true) { $files = array(); for($i = 0; $i < $zip->numFiles; $i++) { $filename = $zip->getNameIndex($i); $files[$filename] = $zip->getFromName($filename); } $zip->close(); } else { $files = false; } return $files; } } ?> phoronix-test-suite/pts-core/objects/pts_result_file_writer.php0000644000175000017500000002262711727435426025337 0ustar michaelmichael. */ class pts_result_file_writer { public $xml_writer = null; private $added_hashes = null; private $result_identifier = null; private $result_count = 0; public function __construct($result_identifier = null, &$xml_writer = null) { $this->result_identifier = $result_identifier; $this->added_hashes = array(); if($xml_writer instanceof nye_XmlWriter) { $this->xml_writer = $xml_writer; } else { $this->xml_writer = new nye_XmlWriter((PTS_IS_CLIENT ? 'pts-results-viewer.xsl' : null)); } } public function get_xml() { return $this->xml_writer->getXML(); } public function get_result_identifier() { return $this->result_identifier; } public function save_xml($to_save) { return $this->xml_writer->saveXMLFile($to_save); } public function get_result_count() { return $this->result_count; } protected function add_result_from_result_object(&$result_object) { $this->xml_writer->addXmlNode('PhoronixTestSuite/Result/Identifier', $result_object->test_profile->get_identifier()); $this->xml_writer->addXmlNode('PhoronixTestSuite/Result/Title', $result_object->test_profile->get_title()); $this->xml_writer->addXmlNode('PhoronixTestSuite/Result/AppVersion', $result_object->test_profile->get_app_version()); $this->xml_writer->addXmlNode('PhoronixTestSuite/Result/Arguments', $result_object->get_arguments()); $this->xml_writer->addXmlNode('PhoronixTestSuite/Result/Description', $result_object->get_arguments_description()); $this->xml_writer->addXmlNode('PhoronixTestSuite/Result/Scale', $result_object->test_profile->get_result_scale()); $this->xml_writer->addXmlNode('PhoronixTestSuite/Result/Proportion', $result_object->test_profile->get_result_proportion()); $this->xml_writer->addXmlNode('PhoronixTestSuite/Result/DisplayFormat', $result_object->test_profile->get_display_format()); $this->result_count++; } public function add_result_from_result_object_with_value_string(&$result_object, $result_value, $result_value_raw = null, $json = null) { $this->add_result_from_result_object($result_object); $this->xml_writer->addXmlNode('PhoronixTestSuite/Result/Data/Entry/Identifier', $this->result_identifier); $this->xml_writer->addXmlNode('PhoronixTestSuite/Result/Data/Entry/Value', $result_value); $this->xml_writer->addXmlNode('PhoronixTestSuite/Result/Data/Entry/RawString', $result_value_raw); if(!defined('USER_PTS_CORE_VERSION') || USER_PTS_CORE_VERSION > 3722) { // Ensure that a supported result file schema is being written... // USER_PTS_CORE_VERSION is set by OpenBenchmarking.org so if the requested client is old, don't write this data to send back to their version $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Result/Data/Entry/JSON', ($json ? json_encode($json) : null)); } } public function add_result_from_result_object_with_value(&$result_object) { $buffer_items = $result_object->test_result_buffer->get_buffer_items(); if(count($buffer_items) == 0) { return false; } $this->add_result_from_result_object($result_object); foreach($buffer_items as $i => &$buffer_item) { $this->xml_writer->addXmlNode('PhoronixTestSuite/Result/Data/Entry/Identifier', $buffer_item->get_result_identifier()); $this->xml_writer->addXmlNode('PhoronixTestSuite/Result/Data/Entry/Value', $buffer_item->get_result_value()); $this->xml_writer->addXmlNode('PhoronixTestSuite/Result/Data/Entry/RawString', $buffer_item->get_result_raw()); if(!defined('USER_PTS_CORE_VERSION') || USER_PTS_CORE_VERSION > 3722) { // Ensure that a supported result file schema is being written... // USER_PTS_CORE_VERSION is set by OpenBenchmarking.org so if the requested client is old, don't write this data to send back to their version $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Result/Data/Entry/JSON', ($buffer_item->get_result_json() ? json_encode($buffer_item->get_result_json()) : null)); } } return true; } public function add_results_from_result_manager(&$result_manager) { foreach($result_manager->get_results() as $result_object) { $this->add_result_from_result_object_with_value($result_object); } } public function add_results_from_result_file(&$result_file) { foreach($result_file->get_result_objects() as $result_object) { $this->add_result_from_result_object_with_value($result_object); } } public function add_test_notes($test_notes, $json = null) { $this->xml_writer->addXmlNode('PhoronixTestSuite/System/Notes', $test_notes); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/System/JSON', ($json ? json_encode($json) : null)); } public function add_result_file_meta_data(&$object, $reference_id = null) { $this->xml_writer->addXmlNode('PhoronixTestSuite/Generated/Title', $object->get_title()); $this->xml_writer->addXmlNode('PhoronixTestSuite/Generated/LastModified', date('Y-m-d H:i:s')); $this->xml_writer->addXmlNode('PhoronixTestSuite/Generated/TestClient', pts_title(true)); $this->xml_writer->addXmlNode('PhoronixTestSuite/Generated/Description', $object->get_description()); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Generated/Notes', $object->get_notes()); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Generated/InternalTags', $object->get_internal_tags()); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Generated/ReferenceID', ($reference_id != null ? $reference_id : $object->get_reference_id())); $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/Generated/PreSetEnvironmentVariables', $object->get_preset_environment_variables()); } public function add_current_system_information() { $this->xml_writer->addXmlNode('PhoronixTestSuite/System/Identifier', $this->result_identifier); $this->xml_writer->addXmlNode('PhoronixTestSuite/System/Hardware', phodevi::system_hardware(true)); $this->xml_writer->addXmlNode('PhoronixTestSuite/System/Software', phodevi::system_software(true)); $this->xml_writer->addXmlNode('PhoronixTestSuite/System/User', pts_client::current_user()); $this->xml_writer->addXmlNode('PhoronixTestSuite/System/TimeStamp', date('Y-m-d H:i:s')); $this->xml_writer->addXmlNode('PhoronixTestSuite/System/TestClientVersion', PTS_VERSION); //$this->xml_writer->addXmlNode('PhoronixTestSuite/System/Notes', pts_test_notes_manager::generate_test_notes($test_type)); } public function add_system_information_from_result_file(&$result_file, $result_merge_select = null) { $system_hardware = $result_file->get_system_hardware(); $system_software = $result_file->get_system_software(); $system_user = $result_file->get_system_user(); $system_date = $result_file->get_system_date(); $pts_version = $result_file->get_system_pts_version(); $system_notes = $result_file->get_system_notes(); $associated_identifiers = $result_file->get_system_identifiers(); $system_json = $result_file->get_system_json(); // Write the system hardware/software information foreach(array_keys($system_hardware) as $i) { if(!($is_pts_rms = ($result_merge_select instanceof pts_result_merge_select)) || $result_merge_select->get_selected_identifiers() == null || in_array($associated_identifiers[$i], $result_merge_select->get_selected_identifiers())) { // Prevents any information from being repeated $this_hash = md5($associated_identifiers[$i] . ';' . $system_hardware[$i] . ';' . $system_software[$i] . ';' . $system_date[$i]); if(!in_array($this_hash, $this->added_hashes)) { if($is_pts_rms && ($renamed = $result_merge_select->get_rename_identifier()) != null) { $associated_identifiers[$i] = $renamed; } $this->xml_writer->addXmlNode('PhoronixTestSuite/System/Identifier', $associated_identifiers[$i]); $this->xml_writer->addXmlNode('PhoronixTestSuite/System/Hardware', $system_hardware[$i]); $this->xml_writer->addXmlNode('PhoronixTestSuite/System/Software', $system_software[$i]); $this->xml_writer->addXmlNode('PhoronixTestSuite/System/User', $system_user[$i]); $this->xml_writer->addXmlNode('PhoronixTestSuite/System/TimeStamp', $system_date[$i]); $this->xml_writer->addXmlNode('PhoronixTestSuite/System/TestClientVersion', $pts_version[$i]); $this->xml_writer->addXmlNode('PhoronixTestSuite/System/Notes', $system_notes[$i]); if(!defined('USER_PTS_CORE_VERSION') || USER_PTS_CORE_VERSION > 3722) { // Ensure that a supported result file schema is being written... // USER_PTS_CORE_VERSION is set by OpenBenchmarking.org so if the requested client is old, don't write this data to send back to their version $this->xml_writer->addXmlNodeWNE('PhoronixTestSuite/System/JSON', ($system_json[$i] ? json_encode($system_json[$i]) : null)); } array_push($this->added_hashes, $this_hash); } } } } } ?> phoronix-test-suite/pts-core/objects/pts_c.php0000644000175000017500000000203711670025163021627 0ustar michaelmichael. */ class pts_c { public static $test_flags = 0; const auto_mode = 2; const batch_mode = 4; const defaults_mode = 8; const debug_mode = 16; const remote_mode = 32; const force_install = 64; const is_recovering = 128; const is_run_process = 256; } ?> phoronix-test-suite/pts-core/objects/pts_test_option.php0000644000175000017500000001245211743102304023750 0ustar michaelmichael. */ class pts_test_option { private $identifier = null; private $option_name = null; private $prefix = null; private $postfix = null; private $default_entry = -1; private $options = array(); public function __construct($identifier, $option) { $this->identifier = $identifier; $this->option_name = $option; } public function set_option_prefix($prefix) { $this->prefix = $prefix; } public function set_option_postfix($postfix) { $this->postfix = $postfix; } public function set_option_default($default_node) { $default_node--; if(isset($this->options[$default_node])) { $this->default_entry = $default_node; } } public function get_identifier() { return $this->identifier; } public function get_name() { return $this->option_name; } public function get_option_prefix() { return $this->prefix; } public function get_option_postfix() { return $this->postfix; } public function get_option_default_raw() { return $this->default_entry == -1 ? 0 : $this->default_entry; } public function get_option_default() { return $this->default_entry == -1 ? $this->option_count() - 1 : $this->default_entry; } public function add_option($name, $value, $message) { array_push($this->options, array($name, $value, $message)); } public function get_options_array() { return $this->options; } public function get_all_option_names() { $names = array(); for($i = 0; $i < $this->option_count(); $i++) { array_push($names, $this->get_option_name($i)); } return $names; } public function get_all_option_names_with_messages() { $names = array(); for($i = 0; $i < $this->option_count(); $i++) { $user_msg = $this->get_option_message($i); array_push($names, $this->get_option_name($i) . (!empty($user_msg) ? ' [' . $user_msg . ']' : null)); } return $names; } public function get_option_name($index) { return isset($this->options[$index][0]) ? $this->options[$index][0] : null; } public function get_option_value($index) { return isset($this->options[$index][1]) ? $this->options[$index][1] : null; } public function get_option_message($index) { return isset($this->options[$index][2]) ? $this->options[$index][2] : null; } public function option_count() { return count($this->options); } public function format_option_value_from_input($input) { return $this->get_option_prefix() . $input . $this->get_option_postfix(); } public function format_option_display_from_input($input) { $name = $this->get_name(); return $name != null && $input != null ? $name . ': ' . $input : null; } public function format_option_value_from_select($select_pos) { $input = $this->get_option_value($select_pos); return $this->format_option_value_from_input($input); } public function format_option_display_from_select($select_pos) { $display_name = $this->get_option_name($select_pos); if(($cut_point = strpos($display_name, '(')) > 1 && strpos($display_name, ')') > $cut_point) { $display_name = trim(substr($display_name, 0, $cut_point)); } return $this->format_option_display_from_input($display_name); } public function is_valid_select_choice($select_pos) { $valid = false; if(is_numeric($select_pos) && $select_pos >= 0 && $select_pos < $this->option_count()) { $valid = $select_pos; } else if(in_array($select_pos, $this->get_all_option_names())) { $match_made = false; for($i = 0; $i < $this->option_count() && !$match_made; $i++) { if($this->get_option_name($i) == $select_pos) { $valid = $i; $match_made = true; } } } return $valid; } public function parse_selection_choice_input($input, $use_default_on_empty = true) { $return_keys = array(); if($input === '0') { array_push($return_keys, 0); } else { foreach(pts_strings::comma_explode($input) as $input_choice) { if($input_choice == $this->option_count() || $input_choice == 'Test All Options') { // Add all options foreach(array_keys($this->options) as $i) { array_push($return_keys, $i); } break; } else if(($c = $this->is_valid_select_choice($input_choice)) !== false) { array_push($return_keys, $c); } } } $return_keys = array_unique($return_keys); sort($return_keys); if($use_default_on_empty && count($return_keys) == 0) { // Use the default as no valid options were presented array_push($return_keys, $this->get_option_default()); } return $return_keys; } } ?> phoronix-test-suite/pts-core/objects/pts_result_merge_select.php0000644000175000017500000000346611564533734025462 0ustar michaelmichael. */ class pts_result_merge_select { private $result_file; private $selected_identifiers; private $rename_identifier; public function __construct($result_file, $selected_identifiers = null) { $this->result_file = $result_file; $this->selected_identifiers = ($selected_identifiers != null ? pts_arrays::to_array($selected_identifiers) : null); $this->rename_identifier = null; } public function get_result_file() { return $this->result_file; } public function get_selected_identifiers() { return $this->selected_identifiers; } public function __toString() { return $this->get_result_file() . ':' . $this->get_selected_identifiers(); } public function rename_identifier($new_name) { // $this->selected_identifers should either contain just the single identifer of what is being renamed or it should be null if being handled through Phoromatic $this->rename_identifier = (count($this->selected_identifiers) < 2 ? $new_name : null); } public function get_rename_identifier() { return $this->rename_identifier; } } ?> phoronix-test-suite/pts-core/objects/pts_tracker.php0000644000175000017500000000543511564533734023057 0ustar michaelmichael. */ class pts_tracker { public static function list_regressions_linear(&$result_file, $threshold = 0.05, $show_only_active_regressions = true) { $regressions = array(); foreach($result_file->get_result_objects() as $test_index => $result_object) { $prev_buffer_item = null; $this_test_regressions = array(); foreach($result_object->test_result_buffer->get_buffer_items() as $buffer_item) { if(!is_numeric($buffer_item->get_result_value())) { break; } if($prev_buffer_item != null && abs(1 - ($buffer_item->get_result_value() / $prev_buffer_item->get_result_value())) > $threshold) { if(defined('PHOROMATIC_TRACKER')) { $explode_r = explode(': ', $buffer_item->get_result_identifier()); $explode_r_prev = explode(': ', $prev_buffer_item->get_result_identifier()); if(count($explode_r) > 1 && $explode_r[0] != $explode_r_prev[0]) { // This case wards against it looking like a regression between multiple systems on a Phoromatic Tracker // The premise is the format is 'SYSTEM NAME: DATE' so match up SYSTEM NAME's continue; } } $this_regression_marker = new pts_test_result_regression_marker($result_object, $prev_buffer_item, $buffer_item, $test_index); if($show_only_active_regressions) { foreach($this_test_regressions as $index => &$regression_marker) { if(abs(1 - ($regression_marker->get_base_value() / $this_regression_marker->get_regressed_value())) < 0.04) { // 1% tolerance, regression seems to be corrected unset($this_test_regressions[$index]); $this_regression_marker = null; break; } } } if($this_regression_marker != null) { array_push($this_test_regressions, $this_regression_marker); } } $prev_buffer_item = $buffer_item; } foreach($this_test_regressions as &$regression_marker) { array_push($regressions, $regression_marker); } } return $regressions; } } ?> phoronix-test-suite/pts-core/objects/pts_merge.php0000644000175000017500000000766211712461234022515 0ustar michaelmichael. */ class pts_merge { public static function merge_test_results_array($files_to_combine, $pass_attributes = null) { $result_file_writer = new pts_result_file_writer(); self::merge_test_results_process($result_file_writer, $files_to_combine, $pass_attributes); return $result_file_writer->get_xml(); } public static function merge_test_results() { // Merge test results // Pass the result file names/paths for each test result file to merge as each as a parameter of the array $files_to_combine = func_get_args(); return self::merge_test_results_array($files_to_combine); } public static function merge_test_results_process(&$result_file_writer, &$files_to_combine, $pass_attributes = null) { $test_result_manager = new pts_result_file_merge_manager($pass_attributes); $has_written_suite_info = false; foreach($files_to_combine as &$file) { if(is_object($file) && $file instanceof pts_result_merge_select) { $result_merge_select = $file; $this_result_file = $result_merge_select->get_result_file(); if(($this_result_file instanceof pts_result_file) == false) { $this_result_file = new pts_result_file($this_result_file); } } else if(is_object($file) && $file instanceof pts_result_file) { if(($t = $file->read_extra_attribute('rename_result_identifier')) != false) { // This code path is currently used by Phoromatic $result_merge_select = new pts_result_merge_select(null, null); $result_merge_select->rename_identifier($t); } else { $result_merge_select = null; } $this_result_file = $file; } else { $result_merge_select = new pts_result_merge_select($file, null); $this_result_file = new pts_result_file($result_merge_select->get_result_file()); } if($this_result_file->get_test_count() == 0) { // Why print the system information if there are no contained results? continue; } if(!isset($pass_attributes['only_render_results_xml'])) { if($has_written_suite_info == false) { $result_file_writer->add_result_file_meta_data($this_result_file); $has_written_suite_info = true; } $result_file_writer->add_system_information_from_result_file($this_result_file, $result_merge_select); } $test_result_manager->add_test_result_set($this_result_file->get_result_objects(), $result_merge_select); } // Write the actual test results $result_file_writer->add_results_from_result_manager($test_result_manager); } public static function generate_analytical_batch_xml($analyze_file) { if(($analyze_file instanceof pts_result_file) == false) { $analyze_file = new pts_result_file($analyze_file); } $result_file_writer = new pts_result_file_writer(); $result_file_writer->add_result_file_meta_data($analyze_file); $result_file_writer->add_system_information_from_result_file($analyze_file); $test_result_manager = new pts_result_file_analyze_manager(); $test_result_manager->add_test_result_set($analyze_file->get_result_objects()); $result_file_writer->add_results_from_result_manager($test_result_manager); unset($test_result_manager); return $result_file_writer->get_xml(); } } ?> phoronix-test-suite/pts-core/objects/pts_test_result_regression_marker.php0000644000175000017500000000514011564533734027573 0ustar michaelmichael. */ class pts_test_result_regression_marker { private $test_identifier; private $test_proportion; private $base_buffer_item; private $regressed_buffer_item; private $result_file_index; private $change; public function __construct(&$result_file_merge_test, $base_buffer_item, $regressed_buffer_item, $result_file_index = -1) { $this->test_identifier = $result_file_merge_test->test_profile->get_identifier(); $this->test_proportion = $result_file_merge_test->test_profile->get_result_proportion(); $this->base_buffer_item = $base_buffer_item; $this->regressed_buffer_item = $regressed_buffer_item; $this->result_file_index = $result_file_index; $this->change = pts_math::set_precision(abs(1 - ($regressed_buffer_item->get_result_value() / $base_buffer_item->get_result_value())), 4); } public function get_test_identifier() { return $this->test_identifier; } public function get_result_file_index() { return $this->result_file_index; } public function get_base_identifier() { return $this->base_buffer_item->get_result_identifier(); } public function get_base_value() { return $this->base_buffer_item->get_result_value(); } public function get_regressed_identifier() { return $this->regressed_buffer_item->get_result_identifier(); } public function get_regressed_value() { return $this->regressed_buffer_item->get_result_value(); } public function get_change() { return $this->change; } 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); } } ?> phoronix-test-suite/pts-core/objects/pts_user_io.php0000644000175000017500000001056511751500676023066 0ustar michaelmichael. */ class pts_user_io { public static function read_user_input() { return trim(fgets(STDIN)); } public static function prompt_user_input($question, $allow_null = false) { do { echo PHP_EOL . $question . ': '; $answer = pts_user_io::read_user_input(); } while(!$allow_null && empty($answer)); return $answer; } public static function display_interrupt_message($message) { if(!empty($message)) { echo $message . PHP_EOL; if((pts_c::$test_flags ^ pts_c::batch_mode) && (pts_c::$test_flags ^ pts_c::auto_mode)) { echo PHP_EOL . 'Hit Any Key To Continue...' . PHP_EOL; pts_user_io::read_user_input(); } } } public static function display_text_list($list_items, $line_start = '- ') { $list = null; foreach($list_items as &$item) { $list .= $line_start . $item . PHP_EOL; } return $list; } public static function display_text_table(&$table) { $column_widths = array(); $formatted_table = null; for($r = 0; $r < count($table); $r++) { for($c = 0; $c < count($table[$r]); $c++) { if(!isset($column_widths[$c]) || isset($table[$r][$c][$column_widths[$c]])) { $column_widths[$c] = strlen($table[$r][$c]); } } } for($r = 0, $r_count = count($table); $r < $r_count; $r++) { for($c = 0, $rc_count = count($table[$r]); $c < $rc_count; $c++) { $formatted_table .= $table[$r][$c]; if(($c + 1) != $rc_count) { $formatted_table .= str_repeat(' ', (1 + $column_widths[$c] - strlen($table[$r][$c]))); } } if(($r + 1) != $r_count) { $formatted_table .= PHP_EOL; } } return $formatted_table; } public static function prompt_bool_input($question, $default = true, $question_id = 'UNKNOWN') { // Prompt user for yes/no question if((pts_c::$test_flags & pts_c::batch_mode)) { switch($question_id) { default: $auto_answer = 'true'; break; } $answer = pts_strings::string_bool($auto_answer); } else { $question .= ' (' . ($default == true ? 'Y/n' : 'y/N') . '): '; do { pts_client::$display->generic_prompt($question); $input = strtolower(pts_user_io::read_user_input()); } while($input != 'y' && $input != 'n' && $input != ''); switch($input) { case 'y': $answer = true; break; case 'n': $answer = false; break; default: $answer = $default; break; } } return $answer; } public static function prompt_text_menu($user_string, $options_r, $allow_multi_select = false, $return_index = false, $line_prefix = null) { $option_count = count($options_r); if($option_count == 1) { return $return_index ? pts_arrays::last_element(array_keys($options_r)) : array_pop($options_r); } $select = array(); do { echo PHP_EOL; $key_index = array(); foreach(array_keys($options_r) as $i => $key) { $key_index[($i + 1)] = $key; echo $line_prefix . ($i + 1) . ': ' . str_repeat(' ', strlen($option_count) - strlen(($i + 1))) . $options_r[$key] . PHP_EOL; } echo $line_prefix . $user_string . ': '; $select_choice = pts_user_io::read_user_input(); foreach(($allow_multi_select ? pts_strings::comma_explode($select_choice) : array($select_choice)) as $choice) { if(in_array($choice, $options_r)) { array_push($select, array_search($choice, $options_r)); } else if(isset($key_index[$choice])) { array_push($select, $key_index[$choice]); } } } while(!isset($select[0])); if($return_index == false) { foreach($select as &$index) { $index = $options_r[$index]; } } return implode(',', $select); } } ?> phoronix-test-suite/pts-core/objects/pts_result_file_merge_manager.php0000644000175000017500000001236211724436615026605 0ustar michaelmichael. */ class pts_result_file_merge_manager { private $test_results = null; private $skip_subsystems = null; private $only_show_select_tests; private $sets_added = 0; private $is_reference_comparison; private $skip_adding_on_extra_sets; public function __construct($pass_attributes = null) { $this->test_results = array(); if(isset($pass_attributes['subsystem_targets_to_skip']) && is_array($pass_attributes['subsystem_targets_to_skip'])) { $this->skip_subsystems = $pass_attributes['subsystem_targets_to_skip']; } $this->is_reference_comparison = isset($pass_attributes['is_reference_comparison']); $this->skip_adding_on_extra_sets = isset($pass_attributes['skip_adding_on_extra_sets']); $this->only_show_select_tests = isset($pass_attributes['select_test_profiles']) ? $pass_attributes['select_test_profiles'] : null; } public function add_test_result_set($merge_test_objects_array, &$result_merge_select) { foreach($merge_test_objects_array as $merge_test_object) { $this->add_test_result($merge_test_object, $result_merge_select); } $this->sets_added += 1; } public function add_test_result($merge_test_object, &$result_merge_select) { $select_identifiers = $result_merge_select instanceof pts_result_merge_select ? $result_merge_select->get_selected_identifiers() : null; $mto_hash = $merge_test_object->get_comparison_hash(); $merged = false; if($this->skip_subsystems != null) { // Check whether to omit rendering this test if only certain subsystem test types should be merged $test_subsystem = $merge_test_object->test_profile->get_test_hardware_type(); if($test_subsystem != null && !in_array($test_subsystem, $this->skip_subsystems)) { return false; } } if($this->only_show_select_tests != null && is_array($this->only_show_select_tests)) { if(!in_array($merge_test_object->test_profile->get_identifier_base_name(), $this->only_show_select_tests)) { return false; } } if(isset($this->test_results[$mto_hash])) { foreach($merge_test_object->test_result_buffer->get_buffer_items() as $buffer_item) { $this_identifier = $buffer_item->get_result_identifier(); if($select_identifiers == null || in_array($this_identifier, $select_identifiers)) { if($result_merge_select != null && ($renamed = $result_merge_select->get_rename_identifier()) != null) { $this_identifier = $renamed; } if($this->result_already_contained($this->test_results[$mto_hash], $buffer_item) == false) { $this->test_results[$mto_hash]->test_result_buffer->add_test_result($this_identifier, $buffer_item->get_result_value(), $buffer_item->get_result_raw(), $buffer_item->get_result_json()); } } } $merged = true; } if($merged == false) { $skip_adding = false; if($result_merge_select != null || is_array($select_identifiers)) { if($this->is_reference_comparison && is_array($select_identifiers)) { $skip_adding = true; } else if($this->skip_adding_on_extra_sets && $this->sets_added > 0) { $skip_adding = true; } $result_buffer = $merge_test_object->test_result_buffer; $merge_test_object->test_result_buffer = new pts_test_result_buffer(); foreach($result_buffer->get_buffer_items() as $buffer_item) { $this_identifier = $buffer_item->get_result_identifier(); if($select_identifiers == null || in_array($this_identifier, $select_identifiers)) { if(($renamed = $result_merge_select->get_rename_identifier()) != null) { $this_identifier = $renamed; } $merge_test_object->test_result_buffer->add_test_result($this_identifier, $buffer_item->get_result_value(), $buffer_item->get_result_raw(), $buffer_item->get_result_json()); } } } else { if($this->skip_adding_on_extra_sets && $this->sets_added > 0) { $skip_adding = true; } } // Add Result if($skip_adding == false) { $this->test_results[$mto_hash] = $merge_test_object; } } } protected function result_already_contained(&$mto_compare, &$buffer_item) { $contained = false; foreach($mto_compare->test_result_buffer->get_buffer_items() as $check_buffer_item) { if($buffer_item->get_result_identifier() == $check_buffer_item->get_result_identifier() && $buffer_item->get_result_value() == $check_buffer_item->get_result_value()) { $contained = true; break; } } return $contained; } public function get_results() { return $this->test_results; } } ?> phoronix-test-suite/pts-core/objects/pts_test_result_buffer.php0000644000175000017500000001122312157131232025304 0ustar michaelmichael. */ class pts_test_result_buffer { public $buffer_items; public function __construct($buffer_items = array()) { $this->buffer_items = $buffer_items; } public function get_buffer_items() { return $this->buffer_items; } public function sort_buffer_items() { sort($this->buffer_items); } public function sort_buffer_values($asc = true) { usort($this->buffer_items, array('pts_test_result_buffer', 'buffer_value_comparison')); if($asc == false) { $this->buffer_items = array_reverse($this->buffer_items); } } public static function buffer_value_comparison($a, $b) { return strcmp($a->get_result_value(), $b->get_result_value()); } public function add_buffer_item($buffer_item) { array_push($this->buffer_items, $buffer_item); } public function get_buffer_item($i) { return isset($this->buffer_items[$i]) ? $this->buffer_items[$i] : false; } public function add_test_result($identifier, $value, $raw_value = null, $json = null, $min_value = null, $max_value = null) { array_push($this->buffer_items, new pts_test_result_buffer_item($identifier, $value, $raw_value, $json, $min_value, $max_value)); } public function clear_outlier_results($add_to_other = true, $value_below = false) { pts_test_result_buffer_extra::clear_outlier_results($this->buffer_items, $add_to_other, $value_below); } public function add_composite_result($force = false) { pts_test_result_buffer_extra::add_composite_result($this, $force); } public function auto_shorten_buffer_identifiers($identifier_shorten_index = false) { // If there's a lot to plot, try to auto-shorten the identifiers // e.g. if each identifier contains like 'GeForce 6800', 'GeForce GT 220', etc.. // then remove the 'GeForce' part of the name. if($identifier_shorten_index == false) { $identifier_shorten_index = pts_render::evaluate_redundant_identifier_words($this->get_identifiers()); } if(empty($identifier_shorten_index)) { return false; } foreach($this->buffer_items as &$buffer_item) { $identifier = explode(' ', $buffer_item->get_result_identifier()); foreach($identifier_shorten_index as $pos => $value) { if($identifier[$pos] == $value) { unset($identifier[$pos]); } } $buffer_item->reset_result_identifier(implode(' ', $identifier)); } return true; } public function clear_iqr_outlier_results() { pts_test_result_buffer_extra::clear_iqr_outlier_results($this); } public function buffer_values_sort() { usort($this->buffer_items, array('pts_test_result_buffer_item', 'compare_value')); } public function buffer_values_reverse() { $this->buffer_items = array_reverse($this->buffer_items); } public function get_count() { return count($this->buffer_items); } public function get_identifiers() { $identifiers = array(); foreach($this->buffer_items as &$buffer_item) { array_push($identifiers, $buffer_item->get_result_identifier()); } return $identifiers; } public function get_values() { $values = array(); foreach($this->buffer_items as &$buffer_item) { array_push($values, $buffer_item->get_result_value()); } return $values; } public function get_min_values() { $values = array(); foreach($this->buffer_items as &$buffer_item) { if(($min = $buffer_item->get_min_result_value()) != null) { array_push($values, $min); } } return $values; } public function get_max_values() { $values = array(); foreach($this->buffer_items as &$buffer_item) { if(($max = $buffer_item->get_max_result_value()) != null) { array_push($values, $max); } } return $values; } public function get_raw_values() { $raw_values = array(); foreach($this->buffer_items as &$buffer_item) { array_push($raw_values, $buffer_item->get_result_raw()); } return $raw_values; } public function get_values_as_string() { return implode(':', $this->get_values()); } } ?> phoronix-test-suite/pts-core/objects/pts_storage_object.php0000644000175000017500000001072411663654164024414 0ustar michaelmichael. */ class pts_storage_object { private $object_cache; private $object_cs; private $creation_time; private $span_reboots; private $span_versions; private $pts_version; public function __construct($span_reboots = true, $span_versions = true) { $this->creation_time = time(); $this->span_reboots = $span_reboots; $this->span_versions = $span_versions; $this->pts_version = PTS_CORE_VERSION; $this->object_cache = array(); } public function add_object($identifier, $object) { $this->object_cache[$identifier] = $object; } public function read_object($identifier) { return isset($this->object_cache[$identifier]) ? $this->object_cache[$identifier] : false; } public function remove_object($identifier) { unset($this->object_cache[$identifier]); } public function get_objects() { return $this->object_cache; } public function save_to_file($destination) { $this->object_cs = md5(serialize($this->get_objects())); // Checksum $string_version = base64_encode(serialize($this)); file_put_contents($destination, wordwrap($string_version, 80, PHP_EOL, true)); } public function get_pts_version() { return $this->pts_version; } public function get_object_checksum() { return $this->object_cs; } public function get_span_reboots() { return $this->span_reboots; } public function get_span_versions() { return $this->span_versions !== false; } public function get_creation_time() { return $this->creation_time; } public function force_recover_from_file($read_from_file) { $restore_obj = false; if(is_file($read_from_file)) { $restore = unserialize(base64_decode(file_get_contents($read_from_file))); if($restore instanceof pts_storage_object) { $restore_obj = $restore; } } return $restore_obj; } public static function recover_from_file($read_from_file) { $restore_obj = false; if(is_file($read_from_file)) { $restore = unserialize(base64_decode(file_get_contents($read_from_file))); if($restore instanceof pts_storage_object) { if(($restore->get_span_versions() || $restore->get_pts_version() == PTS_CORE_VERSION) && md5(serialize($restore->get_objects())) == $restore->get_object_checksum()) { if($restore->get_span_reboots() == false) { $continue_loading = $restore->get_creation_time() > (time() - phodevi::system_uptime()); } else { $continue_loading = true; } if($continue_loading) { $restore_obj = $restore; } } } } return $restore_obj; } public static function set_in_file($storage_file, $identifier, $object) { $storage = self::recover_from_file($storage_file); if($storage != false) { $storage->add_object($identifier, $object); $storage->save_to_file($storage_file); } } public static function remove_in_file($storage_file, $identifier) { $storage = self::recover_from_file($storage_file); if($storage != false) { $storage->remove_object($identifier); $storage->save_to_file($storage_file); } } public static function add_in_file($storage_file, $identifier, $add) { $storage = self::recover_from_file($storage_file); if($storage != false) { $current_value = $storage->read_object($identifier); $current_value = is_numeric($current_value) ? $current_value : 0; $storage->add_object($identifier, $current_value + $add); $storage->save_to_file($storage_file); } } public static function read_from_file($storage_file, $identifier) { $storage = self::recover_from_file($storage_file); $object = false; if($storage != false) { $object = $storage->read_object($identifier); } return $object; } } ?> phoronix-test-suite/pts-core/objects/pts_test_suite_parser.php0000644000175000017500000000775411754655712025200 0ustar michaelmichael. */ class pts_test_suite_parser { protected $identifier; public $xml_parser; public function __construct($identifier) { if(PTS_IS_CLIENT) { $identifier = pts_openbenchmarking::evaluate_string_to_qualifier($identifier, true, 'suite'); } $this->identifier = $identifier; $this->xml_parser = new pts_suite_nye_XmlReader($identifier); } public function __toString() { return $this->get_identifier() . ' [v' . $this->get_version() . ']'; } public function get_identifier($bind_version = true) { $identifier = $this->identifier; if($bind_version == false && ($c = strrpos($identifier, '-'))) { if(pts_strings::is_version(substr($identifier, ($c + 1)))) { $identifier = substr($identifier, 0, $c); } } return $identifier; } public function get_identifier_base_name() { $identifier = basename($this->identifier); if(($s = strrpos($identifier, '-')) !== false) { $post_dash = substr($identifier, ($s + 1)); // If the version is attached, remove it if(pts_strings::is_version($post_dash)) { $identifier = substr($identifier, 0, $s); } } return $identifier; } public function requires_core_version_min() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/SuiteInformation/RequiresCoreVersionMin', 2950); } public function requires_core_version_max() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/SuiteInformation/RequiresCoreVersionMax', 9190); } public function get_description() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/SuiteInformation/Description'); } public function get_title() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/SuiteInformation/Title'); } public function get_version() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/SuiteInformation/Version'); } public function get_maintainer() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/SuiteInformation/Maintainer'); } public function get_suite_type() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/SuiteInformation/TestType'); } public function get_pre_run_message() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/SuiteInformation/PreRunMessage'); } public function get_post_run_message() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/SuiteInformation/PostRunMessage'); } public function get_run_mode() { return $this->xml_parser->getXMLValue('PhoronixTestSuite/SuiteInformation/RunMode'); } public function get_test_names() { return $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Execute/Test'); } public function get_unique_test_names() { return array_unique($this->get_test_names()); } public function get_contained_test_profiles() { $test_names = $this->xml_parser->getXMLArrayValues('PhoronixTestSuite/Execute/Test'); $test_profiles = array(); foreach(array_keys($test_names) as $i) { $obj = pts_types::identifier_to_object($test_names[$i]); if($obj instanceof pts_test_profile) { array_push($test_profiles, $obj); } else if($obj instanceof pts_test_suite) { foreach($obj->get_contained_test_profiles() as $obj) { array_push($test_profiles, $obj); } } } return $test_profiles; } } ?> phoronix-test-suite/pts-core/objects/pts_image.php0000644000175000017500000001006112000020734022446 0ustar michaelmichael. */ class pts_image { public static function imagecreatefromtga($tga_file) { // There is no mainline PHP GD support for reading TGA at this time $handle = fopen($tga_file, 'rb'); $data = fread($handle, filesize($tga_file)); fclose($handle); $pointer = 18; $pixel_x = 0; $pixel_y = 0; $img_width = base_convert(bin2hex(strrev(substr($data, 12, 2))), 16, 10); $img_height = base_convert(bin2hex(strrev(substr($data, 14, 2))), 16, 10); $pixel_depth = base_convert(bin2hex(strrev(substr($data, 16, 1))), 16, 10); $bytes_per_pixel = $pixel_depth / 8; $img = imagecreatetruecolor($img_width, $img_height); while($pointer < strlen($data)) { // right now it's only reading 3 bytes per pixel, even for ETQW and others have a pixel_depth of 32-bit, rather than replacing 3 with $bytes_per_pixel // reading 32-bit TGAs from Enemy Territory: Quake Wars seems to actually work this way even though it's 32-bit // 24-bit should be good in all cases imagesetpixel($img, $pixel_x, ($img_height - $pixel_y), base_convert(bin2hex(strrev(substr($data, $pointer, 3))), 16, 10)); $pixel_x++; if($pixel_x == $img_width) { $pixel_y++; $pixel_x = 0; } $pointer += $bytes_per_pixel; } return $img; } public static function image_file_to_gd($img_file) { $img = false; switch(strtolower(pts_arrays::last_element(explode('.', $img_file)))) { case 'tga': $img = pts_image::imagecreatefromtga($img_file); break; case 'png': $img = imagecreatefrompng($img_file); break; case 'jpg': case 'jpeg': $img = imagecreatefromjpeg($img_file); break; } return $img; } public static function rgb_gd_color_at(&$img, $x, $y) { $rgb = imagecolorat($img, $x, $y); // R, G, B return array(($rgb >> 16) & 0xFF, ($rgb >> 8) & 0xFF, $rgb & 0xFF); } public static function rgb_int_diff($rgb1, $rgb2) { return abs(array_sum($rgb1) - array_sum($rgb2)); } public static function gd_image_delta_composite(&$base_img, &$compare_img, $only_return_changes = true) { $composite = array(); for($x = 0; $x < imagesx($base_img); $x++) { for($y = 0; $y < imagesy($base_img); $y++) { $base_rgb = imagecolorat($base_img, $x, $y); $compare_rgb = imagecolorat($compare_img, $x, $y); $diff_rgb = abs($base_rgb - $compare_rgb); if($only_return_changes == false || $diff_rgb != 0) { $composite[$x][$y] = $diff_rgb; } } } return $composite; } public static function color_pixel_delta(&$base_img, &$compare_img, &$x, &$y) { $color = false; // for now we set to true when it should change, but ultimately should return a color $check_points = array( array($x + 1, $y), array($x - 1, $y), array($x, $y + 1), array($x, $y - 1) ); foreach($check_points as $point_r) { if(pts_image::rgb_int_diff(pts_image::rgb_gd_color_at($base_img, $point_r[0], $point_r[1]), pts_image::rgb_gd_color_at($compare_img, $point_r[0], $point_r[1])) > 12) { $color = array($point_r[0], $point_r[1]); break; } } return $color; } public static function compres_png_image($png_file, $compression_level = 8) { $img = imagecreatefrompng($png_file); if($img) { imagepng($img, $png_file, $compression_level); imagedestroy($img); return true; } return false; } } ?> phoronix-test-suite/pts-core/objects/pts_exdep_generic_parser.php0000664000175000017500000000727012077411312025565 0ustar michaelmichael. */ class pts_exdep_generic_parser { public $struct; public function __construct() { $this->struct = array('external-dependencies' => array('generic-packages' => array())); if(PTS_IS_CLIENT) { $xml_parser = new nye_XmlReader(PTS_EXDEP_PATH . 'xml/generic-packages.xml'); $generic_package_name = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ExternalDependencies/Package/GenericName'); $title = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ExternalDependencies/Package/Title'); $generic_file_check = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ExternalDependencies/Package/FileCheck'); $possible_packages = $xml_parser->getXMLArrayValues('PhoronixTestSuite/ExternalDependencies/Package/PossibleNames'); foreach(array_keys($generic_package_name) as $i) { $this->struct['external-dependencies']['generic-packages'][$generic_package_name[$i]] = $this->get_package_format($title[$i], $generic_file_check[$i], $possible_packages[$i]); } } } public function get_package_format($title = null, $file_check = null, $possible_packages = null) { return array( 'title' => $title, 'file_check' => $file_check, 'possible_packages' => $possible_packages ); } public function get_available_packages() { return array_keys($this->struct['external-dependencies']['generic-packages']); } public function is_package($package) { return isset($this->struct['external-dependencies']['generic-packages'][$package]); } public function get_package_data($package) { return $this->is_package($package) ? $this->struct['external-dependencies']['generic-packages'][$package] : $this->get_package_format(); } public function get_vendors_list() { $package_files = pts_file_io::glob(PTS_EXDEP_PATH . 'xml/*-packages.xml'); foreach($package_files as &$file) { $file = basename(substr($file, 0, strpos($file, '-packages.xml'))); } return $package_files; } public function get_vendors_list_formatted() { $vendors = array(); foreach($this->get_vendors_list() as $vendor) { $exdep_platform_parser = new pts_exdep_platform_parser($vendor); $name = $exdep_platform_parser->get_name(); if($name) { array_push($vendors, $name); } } return $vendors; } public function get_vendor_aliases() { $alias_list = array(); foreach($this->get_vendors_list() as $vendor) { $exdep_platform_parser = new pts_exdep_platform_parser($vendor); $aliases = $exdep_platform_parser->get_aliases(); foreach($aliases as $alias) { array_push($alias_list, $alias); } } return $alias_list; } public function get_vendor_aliases_formatted() { $alias_list = array(); foreach($this->get_vendors_list() as $vendor) { $exdep_platform_parser = new pts_exdep_platform_parser($vendor); $aliases = $exdep_platform_parser->get_aliases_formatted(); foreach($aliases as $alias) { array_push($alias_list, $alias); } } return $alias_list; } } ?> phoronix-test-suite/pts-core/objects/pts_svg_dom_gd.php0000644000175000017500000002514512163107534023523 0ustar michaelmichael. */ pts_svg_dom_gd::setup_default_font(); class pts_svg_dom_gd { protected static $color_table; protected static $default_font; public static function setup_default_font($font = null) { $default_font = self::find_default_font($font); if($default_font) { $font_type = basename($default_font); if($default_font != $font_type && !defined('CUSTOM_FONT_DIR')) { define('CUSTOM_FONT_DIR', dirname($default_font)); } self::$default_font = $font_type; } if(getenv('GDFONTPATH') == false) { if(defined('CUSTOM_FONT_DIR')) { putenv('GDFONTPATH=' . CUSTOM_FONT_DIR); } else if(defined('FONT_DIR')) { putenv('GDFONTPATH=' . FONT_DIR); } else if(($font_env = getenv('FONT_DIR')) != false) { putenv('GDFONTPATH=' . $font_env); } else { putenv('GDFONTPATH=' . getcwd()); } } } public static function find_default_font($find_font) { if(!defined('BILDE_DEFAULT_FONT')) { if(is_readable($find_font)) { $default_font = $find_font; }/* else if(ini_get('open_basedir')) { $default_font = false; }*/ else { $default_font = false; $possible_fonts = array( '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf', '/usr/share/fonts/truetype/freefont/FreeSans.ttf', '/usr/share/fonts/truetype/ttf-bitstream-vera/Vera.ttf', '/usr/share/fonts/dejavu/DejaVuSans.ttf', '/usr/share/fonts/liberation/LiberationSans-Regular.ttf', '/usr/share/fonts/truetype/DejaVuSans.ttf', '/usr/share/fonts/truetype/LiberationSans-Regular.ttf', '/usr/share/fonts/TTF/dejavu/DejaVuSans.ttf', '/usr/share/fonts/TTF/liberation/LiberationSans-Regular.ttf', '/usr/X11/lib/X11/fonts/TrueType/arphic/uming.ttf', '/usr/local/lib/X11/fonts/bitstream-vera/Vera.ttf', '/Library/Fonts/Courier New.ttf', '/Library/Fonts/Trebuchet MS.ttf' ); foreach($possible_fonts as $font_file) { if(is_readable($font_file)) { $default_font = $font_file; break; } } } define('BILDE_DEFAULT_FONT', $default_font); } return BILDE_DEFAULT_FONT; } public static function svg_dom_to_gd($dom, $format) { if(extension_loaded('gd') && function_exists('imagettftext') && $dom->childNodes->item(2)->nodeName == 'svg') { $width = $dom->childNodes->item(2)->attributes->getNamedItem('width')->nodeValue; $height = $dom->childNodes->item(2)->attributes->getNamedItem('height')->nodeValue; if($width > 1 && $height > 1) { $gd = imagecreatetruecolor($width, $height); if(!isset($_REQUEST['svg_dom_gd_no_interlacing'])) { // PHP FPDF fails on image interlacing imageinterlace($gd, true); } if(function_exists('imageantialias')) { imageantialias($gd, true); } } else { return false; } //foreach($dom->childNodes->item(2)->attributes as $atrr) // { echo $atrr->name . ' ' . $atrr->value . PHP_EOL; } } else { // If the first tag isn't an svg tag, chances are something is broke... return false; } self::$color_table = array(); foreach($dom->childNodes->item(2)->childNodes as $node) { if($node->nodeName == 'a') { // This is just a link so get whatever is the child of the embedded link to display $node = $node->childNodes->item(0); } switch($node->nodeName) { case 'svg': // Not relevant at this point to GD rendering break; case 'line': $a = self::attributes_to_array($node, array('x1', 'y1', 'x2', 'y2', 'stroke', 'stroke-width', 'stroke-dasharray')); $line_color = self::gd_color_allocate($gd, $a['stroke']); if($a['stroke-dasharray'] != null) { list($dash_length, $blank_length) = explode(',', $a['stroke-dasharray']); if($a['y1'] == $a['y2']) { for($i = $a['x1']; $i < $a['x2']; $i += ($blank_length + $dash_length)) { imagefilledrectangle($gd, $i, ($a['y1'] - floor($a['stroke-width'] / 2)), ($i + $dash_length), ($a['y1'] + floor($a['stroke-width'] / 2)), $line_color); //imageline($gd, $i, $pos, ($i + $dash_length), $pos, $line_color); } } else { for($i = $a['y1']; $i < $a['y2']; $i += ($blank_length + $dash_length)) { imagefilledrectangle($gd, ($a['x1'] - floor($a['stroke-width'] / 2)), $i, ($a['x1'] + floor($a['stroke-width'] / 2)), ($i + $dash_length), $line_color); //imageline($gd, $i, $pos, ($i + $dash_length), $pos, $line_color); } } } else { imagesetthickness($gd, $a['stroke-width']); imageline($gd, $a['x1'], $a['y1'], $a['x2'], $a['y2'], $line_color); } break; case 'polyline': $a = self::attributes_to_array($node, array('points', 'stroke', 'stroke-width', 'fill')); imagesetthickness($gd, $a['stroke-width']); $line_color = self::gd_color_allocate($gd, $a['stroke']); $a['points'] = explode(' ', $a['points']); for($i = 1; $i < count($a['points']); $i++) { $s_point = explode(',', $a['points'][($i - 1)]); $e_point = explode(',', $a['points'][$i]); imageline($gd, $s_point[0], $s_point[1], $e_point[0], $e_point[1], $line_color); } break; case 'text': $a = self::attributes_to_array($node, array('x', 'y', 'font-size', 'text-anchor', 'fill', 'dominant-baseline', 'transform')); $text = $node->nodeValue; $a['font-size'] -= 1.6; $box_array = imagettfbbox($a['font-size'], 0, self::$default_font, $text); $box_width = $box_array[4] - $box_array[6]; $box_height = $box_array[1] - $box_array[7]; $rotate = 0; if($a['transform']) { $rotate = substr($a['transform'], 7); $rotate = substr($rotate, 0, strpos($rotate, ' ')); // $rotate this should be the rotation degree in SVG if($rotate != 0) { $rotate += 180; } switch($a['text-anchor']) { case 'middle': $a['y'] -= round($box_width / 2); break; } } else { switch($a['text-anchor']) { case 'start': break; case 'middle': $a['x'] -= round($box_width / 2); break; case 'end': $a['x'] -= $box_width - 4; break; } switch($a['dominant-baseline']) { case 'text-before-edge': $a['y'] += $box_height; break; case 'middle': $a['y'] += round($box_height / 2); break; } } imagettftext($gd, $a['font-size'], $rotate, $a['x'], $a['y'], self::gd_color_allocate($gd, $a['fill']), self::$default_font, $text); break; case 'polygon': $a = self::attributes_to_array($node, array('points', 'fill', 'stroke', 'stroke-width')); $a['points'] = explode(' ', $a['points']); $points = array(); foreach($a['points'] as &$point) { $point = explode(',', $point); array_push($points, $point[0]); array_push($points, $point[1]); } if($a['stroke-width']) { imagesetthickness($gd, $a['stroke-width']); imagefilledpolygon($gd, $points, count($a['points']), self::gd_color_allocate($gd, $a['stroke'])); } imagefilledpolygon($gd, $points, count($a['points']), self::gd_color_allocate($gd, $a['fill'])); break; case 'rect': // Draw a rectangle $a = self::attributes_to_array($node, array('x', 'y', 'width', 'height', 'fill', 'stroke', 'stroke-width')); if($a['fill'] != 'none') { imagefilledrectangle($gd, $a['x'], $a['y'], ($a['x'] + $a['width']), ($a['y'] + $a['height']), self::gd_color_allocate($gd, $a['fill'])); } if($a['stroke'] != null) { // TODO: implement $a['stroke-width'] imagerectangle($gd, $a['x'], $a['y'], ($a['x'] + $a['width']), ($a['y'] + $a['height']), self::gd_color_allocate($gd, $a['stroke'])); } break; case 'ellipse': // Draw a ellipse/circle $a = self::attributes_to_array($node, array('cx', 'cy', 'rx', 'ry', 'fill', 'stroke', 'stroke-width')); imagefilledellipse($gd, $a['cx'], $a['cy'], ($a['rx'] * 2), ($a['ry'] * 2), self::gd_color_allocate($gd, $a['fill'])); if($a['stroke'] != null) { // TODO: implement $a['stroke-width'] imagefilledellipse($gd, $a['cx'], $a['cy'], ($a['rx'] * 2), ($a['ry'] * 2), self::gd_color_allocate($gd, $a['stroke'])); } break; case 'image': $a = self::attributes_to_array($node, array('xlink:href', 'x', 'y', 'width', 'height')); if(substr($a['xlink:href'], 0, 22) == 'data:image/png;base64,') { $img = imagecreatefromstring(base64_decode(substr($a['xlink:href'], 22))); } else { $img = imagecreatefromstring(file_get_contents($a['xlink:href'])); } imagecopyresampled($gd, $img, $a['x'], $a['y'], 0, 0, $a['width'], $a['height'], imagesx($img), imagesy($img)); break; default: if(PTS_IS_CLIENT) { echo $node->nodeName . ' not implemented.' . PHP_EOL; } break; } // imagejpeg($this->image, $output_file, $quality); //var_dump($node->attributes); } $tmp_output = tempnam('/tmp', 'pts-gd'); switch($format) { case 'JPEG': imagejpeg($gd, $tmp_output, 100); $output = file_get_contents($tmp_output); unlink($tmp_output); break; case 'PNG': imagepng($gd, $tmp_output, 1); $output = file_get_contents($tmp_output); unlink($tmp_output); break; } return $output; } protected static function gd_color_allocate(&$gd, $hex) { if(!isset(self::$color_table[$hex])) { self::$color_table[$hex] = imagecolorallocate($gd, hexdec(substr($hex, 1, 2)), hexdec(substr($hex, 3, 2)), hexdec(substr($hex, 5, 2))); } return self::$color_table[$hex]; } protected static function attributes_to_array(&$node, $attrs) { $values = array(); foreach($attrs as $attribute) { $values[$attribute] = $node->attributes->getNamedItem($attribute) ? $node->attributes->getNamedItem($attribute)->nodeValue : false; } return $values; } } ?> phoronix-test-suite/pts-core/objects/pts_network.php0000644000175000017500000002363612222302672023103 0ustar michaelmichael. */ class pts_network { private static $disable_network_support = false; private static $network_proxy = false; public static function is_proxy_setup() { return self::$network_proxy == false; } public static function network_support_available() { return self::$disable_network_support == false; } public static function http_get_contents($url, $override_proxy = false, $override_proxy_port = false) { if(!pts_network::network_support_available()) { return false; } $stream_context = pts_network::stream_context_create(null, $override_proxy, $override_proxy_port); $contents = pts_file_io::file_get_contents($url, 0, $stream_context); return $contents; } public static function http_upload_via_post($url, $to_post_data) { if(!pts_network::network_support_available()) { return false; } $upload_data = http_build_query($to_post_data); $http_parameters = array('http' => array('method' => 'POST', 'content' => $upload_data)); $stream_context = pts_network::stream_context_create($http_parameters); $opened_url = fopen($url, 'rb', false, $stream_context); $response = $opened_url ? stream_get_contents($opened_url) : false; return $response; } public static function download_file($download, $to) { if(!pts_network::network_support_available()) { return false; } if(function_exists('curl_init') && stripos(PTS_PHP_VERSION, 'hiphop') === false) { // XXX: Facebook HipHop HHVM currently seems to have problems with PHP CURL $return_state = pts_network::curl_download($download, $to); } else { $return_state = pts_network::stream_download($download, $to); } //echo '\nPHP CURL must either be installed or you must adjust your PHP settings file to support opening FTP/HTTP streams.\n'; //return false; if($return_state == true) { pts_client::$display->test_install_progress_completed(); } } public static function curl_download($download, $download_to) { if(!function_exists('curl_init')) { return false; } // with curl_multi_init we could do multiple downloads at once... $cr = curl_init(); $fh = fopen($download_to, 'w'); curl_setopt($cr, CURLOPT_FILE, $fh); curl_setopt($cr, CURLOPT_URL, $download); curl_setopt($cr, CURLOPT_HEADER, false); curl_setopt($cr, CURLOPT_FOLLOWLOCATION, true); curl_setopt($cr, CURLOPT_CONNECTTIMEOUT, (defined('NETWORK_TIMEOUT') ? NETWORK_TIMEOUT : 20)); curl_setopt($cr, CURLOPT_CAPATH, PTS_CORE_STATIC_PATH . 'certificates/'); curl_setopt($cr, CURLOPT_BUFFERSIZE, 64000); curl_setopt($cr, CURLOPT_USERAGENT, pts_codename(true)); if(stripos($download, 'sourceforge') === false) { // Setting the referer causes problems for SourceForge downloads curl_setopt($cr, CURLOPT_REFERER, 'http://www.phoronix-test-suite.com/'); } if(strpos($download, 'https://openbenchmarking.org/') !== false) { curl_setopt($cr, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($cr, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($cr, CURLOPT_CAINFO, PTS_CORE_STATIC_PATH . 'certificates/openbenchmarking-server.pem'); } else if(strpos($download, 'https://www.phoromatic.com/') !== false) { curl_setopt($cr, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($cr, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($cr, CURLOPT_CAINFO, PTS_CORE_STATIC_PATH . 'certificates/phoromatic-com.pem'); } if(PHP_VERSION_ID >= 50300 && defined('CURLOPT_PROGRESSFUNCTION')) { // CURLOPT_PROGRESSFUNCTION only seems to work with PHP 5.3+, but is not working with HipHop HHVM ~2.0.1 curl_setopt($cr, CURLOPT_NOPROGRESS, false); curl_setopt($cr, CURLOPT_PROGRESSFUNCTION, array('pts_network', 'curl_status_callback')); } if(self::$network_proxy) { curl_setopt($cr, CURLOPT_PROXY, self::$network_proxy['proxy']); } curl_exec($cr); curl_close($cr); fclose($fh); return true; } public static function stream_download($download, $download_to, $stream_context_parameters = null, $callback_function = array('pts_network', 'stream_status_callback')) { $stream_context = pts_network::stream_context_create($stream_context_parameters); if(function_exists('stream_context_set_params')) { // HHVM 2.1 doesn't have stream_context_set_params() stream_context_set_params($stream_context, array('notification' => $callback_function)); } /* if(strpos($download, 'https://openbenchmarking.org/') !== false) { stream_context_set_option($stream_context, 'ssl', 'local_cert', PTS_CORE_STATIC_PATH . 'certificates/openbenchmarking-server.pem'); } else if(strpos($download, 'https://www.phoromatic.com/') !== false) { stream_context_set_option($stream_context, 'ssl', 'local_cert', PTS_CORE_STATIC_PATH . 'certificates/phoromatic-com.pem'); } */ $file_pointer = @fopen($download, 'r', false, $stream_context); if(is_resource($file_pointer) && file_put_contents($download_to, $file_pointer)) { return true; } return false; } public static function stream_context_create($parameters = null, $proxy_address = false, $proxy_port = false) { if(!is_array($parameters)) { $parameters = array(); } if($proxy_address == false && $proxy_port == false && self::$network_proxy) { $proxy_address = self::$network_proxy['address']; $proxy_port = self::$network_proxy['port']; } if($proxy_address != false && $proxy_port != false && is_numeric($proxy_port)) { $parameters['http']['proxy'] = 'tcp://' . $proxy_address . ':' . $proxy_port; $parameters['http']['request_fulluri'] = true; } $parameters['http']['timeout'] = defined('NETWORK_TIMEOUT') ? NETWORK_TIMEOUT : 20; $parameters['http']['user_agent'] = pts_codename(true); $parameters['http']['header'] = "Content-Type: application/x-www-form-urlencoded\r\n"; $stream_context = stream_context_create($parameters); return $stream_context; } // // Callback Functions // public static function stream_status_callback($notification_code, $arg1, $message, $message_code, $downloaded, $download_size) { static $filesize = 0; static $last_float = -1; switch($notification_code) { case STREAM_NOTIFY_FILE_SIZE_IS: $filesize = $download_size; break; case STREAM_NOTIFY_PROGRESS: $downloaded_float = $filesize == 0 ? 0 : $downloaded / $filesize; if(abs($downloaded_float - $last_float) < 0.01) { return; } pts_client::$display->test_install_progress_update($downloaded_float); $last_float = $downloaded_float; break; } } private static function curl_status_callback($download_size, $downloaded) { static $last_float = -1; $downloaded_float = $download_size == 0 ? 0 : $downloaded / $download_size; if(abs($downloaded_float - $last_float) < 0.01) { return; } pts_client::$display->test_install_progress_update($downloaded_float); $last_float = $downloaded_float; } public static function client_startup() { if(($proxy_address = pts_config::read_user_config('PhoronixTestSuite/Options/Networking/ProxyAddress', false)) && ($proxy_port = pts_config::read_user_config('PhoronixTestSuite/Options/Networking/ProxyPort', false))) { self::$network_proxy['proxy'] = $proxy_address . ':' . $proxy_port; self::$network_proxy['address'] = $proxy_address; self::$network_proxy['port'] = $proxy_port; } else if(($env_proxy = getenv('http_proxy')) != false && count($env_proxy = pts_strings::colon_explode($env_proxy)) == 2) { self::$network_proxy['proxy'] = $env_proxy[0] . ':' . $env_proxy[1]; self::$network_proxy['address'] = $env_proxy[0]; self::$network_proxy['port'] = $env_proxy[1]; } pts_define('NETWORK_TIMEOUT', pts_config::read_user_config('PhoronixTestSuite/Options/Networking/Timeout', 20)); if(ini_get('allow_url_fopen') == 'Off') { echo PHP_EOL . 'The allow_url_fopen option in your PHP configuration must be enabled for network support.' . PHP_EOL . PHP_EOL; self::$disable_network_support = true; } else if(pts_config::read_bool_config('PhoronixTestSuite/Options/Networking/NoNetworkCommunication', 'FALSE')) { echo PHP_EOL . 'Network Communication Is Disabled For Your User Configuration.' . PHP_EOL . PHP_EOL; self::$disable_network_support = true; } else if(pts_flags::no_network_communication() == true) { //echo PHP_EOL . 'Network Communication Is Disabled For Your User Configuration.' . PHP_EOL . PHP_EOL; self::$disable_network_support = true; } else { $server_response = pts_network::http_get_contents('http://www.phoronix-test-suite.com/PTS', false, false); if($server_response != 'PTS') { // Failed to connect to PTS server // As a last resort, see if it can resolve IP to Google.com as a test for Internet connectivity... // i.e. in case Phoronix server is down or some other issue, so just see if Google will resolve // If google.com fails to resolve, it will simply return the original string if(gethostbyname('google.com') == 'google.com') { echo PHP_EOL; trigger_error('No Network Connectivity', E_USER_WARNING); self::$disable_network_support = true; } } } if(pts_network::network_support_available() == false && ini_get('file_uploads') == 'Off') { echo PHP_EOL . 'The file_uploads option in your PHP configuration must be enabled for network support.' . PHP_EOL . PHP_EOL; } } } ?> phoronix-test-suite/pts-core/objects/pts_openbenchmarking.php0000644000175000017500000005300412222302672024714 0ustar michaelmichael. */ class pts_openbenchmarking { public static function stats_hardware_list() { return array( 'cpu' => array('cpu', 'model'), 'cpu_count' => array('cpu', 'core-count'), 'cpu_speed' => array('cpu', 'mhz-default-frequency'), 'chipset' => array('chipset'), 'motherboard' => array('motherboard'), 'gpu' => array('gpu', 'model'), 'disk' => array('disk', 'identifier'), 'audio' => array('audio', 'identifier'), 'monitor' => array('monitor', 'identifier') ); } public static function valid_user_name() { $invalid_users = array('pts', 'phoronix', 'local'); // TODO: finish function } public static function stats_software_list() { return array( 'os' => array('system', 'operating-system'), 'os_architecture' => array('system', 'kernel-architecture'), 'kernel' => array('system', 'kernel'), 'display_server' => array('system', 'display-server'), 'display_driver' => array('system', 'display-driver-string'), 'opengl' => array('system', 'opengl-driver'), 'desktop' => array('system', 'desktop-environment'), 'compiler' => array('system', 'compiler'), 'file_system' => array('system', 'filesystem'), 'screen_resolution' => array('gpu', 'screen-resolution-string') ); } public static function is_valid_gsid_format($gsid) { $gsid_valid = false; if(strlen($gsid) == 9) { if(ctype_upper(substr($gsid, 0, 6)) && ctype_digit(substr($gsid, 6, 3))) { $gsid_valid = true; } } return $gsid_valid; } public static function is_valid_gsid_e_format($gside) { $gside_valid = false; if(strlen($gside) == 12) { if(ctype_upper(substr($gside, 0, 10)) && ctype_digit(substr($gside, 10, 2))) { $gside_valid = true; } } return $gside_valid; } public static function is_valid_gsid_p_format($gsidp) { $gsidp_valid = false; if(strlen($gsidp) == 10) { if(ctype_upper(substr($gsidp, 0, 9)) && ctype_digit(substr($gsidp, 9, 1))) { $gsidp_valid = true; } } return $gsidp_valid; } public static function is_openbenchmarking_result_id($id) { $is_id = false; if(self::is_string_openbenchmarking_result_id_compliant($id)) { $json_response = pts_openbenchmarking::make_openbenchmarking_request('is_openbenchmarking_result', array('i' => $id)); $json_response = json_decode($json_response, true); if(is_array($json_response) && isset($json_response['openbenchmarking']['result']['valid']) && $json_response['openbenchmarking']['result']['valid'] == 'TRUE') { $is_id = true; } } return $is_id; } public static function clone_openbenchmarking_result(&$id, $return_xml = false) { $json_response = pts_openbenchmarking::make_openbenchmarking_request('clone_openbenchmarking_result', array('i' => $id)); $json_response = json_decode($json_response, true); $valid = false; if(is_array($json_response) && isset($json_response['openbenchmarking']['result']['composite_xml'])) { $composite_xml = $json_response['openbenchmarking']['result']['composite_xml']; $result_file = new pts_result_file($composite_xml); if($result_file->xml_parser->validate()) { $result_file_writer = new pts_result_file_writer(); $result_file_writer->add_result_file_meta_data($result_file, $id); $result_file_writer->add_system_information_from_result_file($result_file); $result_file_writer->add_results_from_result_file($result_file); //$id = strtolower($id); $valid = $return_xml ? $result_file_writer->get_xml() : pts_client::save_test_result($id . '/composite.xml', $result_file_writer->get_xml(), true); if(PTS_IS_CLIENT && $json_response['openbenchmarking']['result']['system_logs_available']) { // Fetch the system logs and toss them into the results directory system-logs/ pts_openbenchmarking::clone_openbenchmarking_result_system_logs($id, pts_client::setup_test_result_directory($id), $json_response['openbenchmarking']['result']['system_logs_available']); } } else { trigger_error('Validating the result file schema failed.', E_USER_ERROR); } } else if(PTS_IS_CLIENT && isset($json_response['openbenchmarking']['result']['error'])) { trigger_error($json_response['openbenchmarking']['result']['error'], E_USER_ERROR); } return $valid; } public static function clone_openbenchmarking_result_system_logs(&$id, $extract_to, $sha1_compare = null) { $system_log_response = pts_openbenchmarking::make_openbenchmarking_request('clone_openbenchmarking_system_logs', array('i' => $id)); $extracted = false; if($system_log_response != null) { $zip_temp = pts_client::create_temporary_file(); file_put_contents($zip_temp, $system_log_response); if($sha1_compare == null || sha1_file($zip_temp) == $sha1_compare) { // hash check of file passed or was null $extracted = pts_compression::zip_archive_extract($zip_temp, $extract_to); } unlink($zip_temp); } return $extracted; } public static function is_string_openbenchmarking_result_id_compliant($id) { $valid = false; if(strlen($id) == 22) { $segments = explode('-', $id); if(count($segments) == 3) { if(strlen($segments[0]) == 7 && is_numeric($segments[0])) { $us = strlen($segments[1]); if($us > 1 && $us < 9 && ctype_alnum($segments[1])) { if(ctype_alnum($segments[2])) { $valid = true; } } } } } return $valid; } public static function is_abstract_id($id) { $valid = false; if(strlen($id) == 4) { if(ctype_alpha($id)) { $valid = true; } } return $valid; } public static function openbenchmarking_host() { static $host = null; if($host == null) { // Use HTTPS if OpenSSL is available as a check to see if HTTPS can be handled // OpenSSL seems to have problems on OpenIndiana at least, TODO: investigate // Using a proxy seems to have problems for HTTPS $host = ((extension_loaded('openssl') && getenv('NO_OPENSSL') == false && php_uname('s') == 'Linux' && (!PTS_IS_CLIENT || !pts_network::is_proxy_setup())) ? 'https://' : 'http://') . 'openbenchmarking.org/'; } return $host; } public static function refresh_repository_lists($repos = null, $force_refresh = false) { if($repos == null) { if($force_refresh == false) { if(!defined('HAS_REFRESHED_OBO_LIST')) { pts_define('HAS_REFRESHED_OBO_LIST', true); } else { return true; } } $repos = self::linked_repositories(); } foreach($repos as $repo_name) { pts_file_io::mkdir(PTS_OPENBENCHMARKING_SCRATCH_PATH . $repo_name); if($repo_name == 'local') { // Local is a special case, not actually a real repository continue; } if(!is_dir(PTS_OPENBENCHMARKING_SCRATCH_PATH . $repo_name)) { mkdir(PTS_OPENBENCHMARKING_SCRATCH_PATH . $repo_name, 0777, true); } $index_file = PTS_OPENBENCHMARKING_SCRATCH_PATH . $repo_name . '.index'; if(is_file($index_file)) { $repo_index = json_decode(file_get_contents($index_file), true); $generated_time = $repo_index['main']['generated']; // Refreshing the indexes once every few days should be suffice // Refresh approximately every three days by default $index_cache_ttl = 3; if(PTS_IS_CLIENT && ($config_ttl = pts_config::read_user_config('PhoronixTestSuite/Options/OpenBenchmarking/IndexCacheTTL'))) { if($config_ttl === 0) { // if the value is 0, only rely upon manual refreshes continue; } else if(is_numeric($config_ttl) && $config_ttl >= 1) { $index_cache_ttl = $config_ttl; } } if($generated_time > (time() - (86400 * $index_cache_ttl)) && $force_refresh == false && (!defined('FIRST_RUN_ON_PTS_UPGRADE') || FIRST_RUN_ON_PTS_UPGRADE == false)) { // The index is new enough continue; } } $server_index = pts_openbenchmarking::make_openbenchmarking_request('repo_index', array('repo' => $repo_name)); if(json_decode($server_index) != false) { file_put_contents($index_file, $server_index); } else if(PTS_IS_CLIENT && is_file('/var/cache/phoronix-test-suite/openbenchmarking.org/' . $repo_name . '.index')) { copy('/var/cache/phoronix-test-suite/openbenchmarking.org/' . $repo_name . '.index', $index_file); } if(!is_file($index_file)) { static $reported_read_failure_notice; if(!isset($reported_read_failure_notice[$repo_name]) && PTS_IS_CLIENT) { trigger_error('Failed To Fetch OpenBenchmarking.org Repository Data: ' . $repo_name, E_USER_WARNING); $reported_read_failure_notice[$repo_name] = true; } } } } public static function linked_repositories() { $repos = array('local', 'pts'); if(PTS_IS_CLIENT && pts_openbenchmarking_client::user_name() != false) { array_push($repos, pts_openbenchmarking_client::user_name()); } return $repos; } public static function make_openbenchmarking_request($request, $post = array()) { $url = pts_openbenchmarking::openbenchmarking_host() . 'f/client.php'; $to_post = array_merge(array( 'r' => $request, 'client_version' => PTS_CORE_VERSION, 'gsid' => (defined('PTS_GSID') ? PTS_GSID : null), 'gsid_e' => (defined('PTS_GSID_E') ? PTS_GSID_E : null) ), $post); if(PTS_IS_CLIENT && ($account = pts_openbenchmarking_client::get_openbenchmarking_account()) && is_array($account)) { $to_post = array_merge($to_post, $account); } return pts_network::http_upload_via_post($url, $to_post); } public static function read_repository_index($repo_name) { $index_file = PTS_OPENBENCHMARKING_SCRATCH_PATH . $repo_name . '.index'; if(is_file($index_file)) { $index_file = file_get_contents($index_file); $index_file = json_decode($index_file, true); } return $index_file; } public static function download_test_profile($qualified_identifier) { if(is_file(PTS_TEST_PROFILE_PATH . $qualified_identifier . '/test-definition.xml')) { return true; } $file = PTS_OPENBENCHMARKING_SCRATCH_PATH . $qualified_identifier . '.zip'; $hash_json = pts_openbenchmarking::make_openbenchmarking_request('test_hash', array('i' => $qualified_identifier)); $hash_json = json_decode($hash_json, true); $hash_check = isset($hash_json['openbenchmarking']['test']['hash']) ? $hash_json['openbenchmarking']['test']['hash'] : null; // should also check for ['openbenchmarking']['test']['error'] problems if(!is_file($file)) { $test_profile = pts_openbenchmarking::make_openbenchmarking_request('download_test', array('i' => $qualified_identifier)); if($test_profile != null && ($hash_check == null || $hash_check == sha1($test_profile))) { // save it file_put_contents($file, $test_profile); $hash_check = null; } else if(is_file('/var/cache/phoronix-test-suite/openbenchmarking.org/' . $qualified_identifier . '.zip') && ($hash_check == null || sha1_file('/var/cache/phoronix-test-suite/openbenchmarking.org/' . $qualified_identifier . '.zip') == $hash_check)) { copy('/var/cache/phoronix-test-suite/openbenchmarking.org/' . $qualified_identifier . '.zip', $file); } else if(PTS_IS_CLIENT && $test_profile === false) { trigger_error('Network support is needed to obtain ' . $qualified_identifier . ' data.' . PHP_EOL, E_USER_ERROR); return false; } } if(!is_file(PTS_TEST_PROFILE_PATH . $qualified_identifier . '/test-definition.xml') && is_file($file) && ($hash_check == null || sha1_file($file) == $hash_check)) { // extract it pts_file_io::mkdir(PTS_TEST_PROFILE_PATH . dirname($qualified_identifier)); pts_file_io::mkdir(PTS_TEST_PROFILE_PATH . $qualified_identifier); return pts_compression::zip_archive_extract($file, PTS_TEST_PROFILE_PATH . $qualified_identifier); } return false; } public static function available_tests($download_tests = true) { $available_tests = array(); foreach(self::linked_repositories() as $repo) { $repo_index = pts_openbenchmarking::read_repository_index($repo); if(isset($repo_index['tests']) && is_array($repo_index['tests'])) { foreach(array_keys($repo_index['tests']) as $identifier) { if($download_tests && pts_network::network_support_available()) { $version = array_shift($repo_index['tests'][$identifier]['versions']); if(self::download_test_profile($repo . '/' . $identifier . '-' . $version) == false) { continue; } } array_push($available_tests, $repo . '/' . $identifier); } } } return $available_tests; } public static function available_suites($download_suites = true) { $available_suites = array(); foreach(self::linked_repositories() as $repo) { $repo_index = pts_openbenchmarking::read_repository_index($repo); if(isset($repo_index['suites']) && is_array($repo_index['suites'])) { foreach(array_keys($repo_index['suites']) as $identifier) { if($download_suites && pts_network::network_support_available()) { $version = array_shift($repo_index['suites'][$identifier]['versions']); if(self::download_test_suite($repo . '/' . $identifier . '-' . $version) == false) { continue; } } array_push($available_suites, $repo . '/' . $identifier); } } } return $available_suites; } public static function download_test_suite($qualified_identifier) { if(is_file(PTS_TEST_SUITE_PATH . $qualified_identifier . '/suite-definition.xml')) { return true; } $file = PTS_OPENBENCHMARKING_SCRATCH_PATH . $qualified_identifier . '.zip'; $hash_json = pts_openbenchmarking::make_openbenchmarking_request('suite_hash', array('i' => $qualified_identifier)); $hash_json = json_decode($hash_json, true); $hash_check = isset($hash_json['openbenchmarking']['suite']['hash']) ? $hash_json['openbenchmarking']['suite']['hash'] : null; // should also check for ['openbenchmarking']['suite']['error'] problems if(!is_file($file)) { $test_suite = pts_openbenchmarking::make_openbenchmarking_request('download_suite', array('i' => $qualified_identifier)); if($test_suite != null && ($hash_check == null || $hash_check == sha1($test_suite))) { // save it file_put_contents($file, $test_suite); $hash_check = null; } else if(is_file('/var/cache/phoronix-test-suite/openbenchmarking.org/' . $qualified_identifier . '.zip') && ($hash_check == null || sha1_file('/var/cache/phoronix-test-suite/openbenchmarking.org/' . $qualified_identifier . '.zip') == $hash_check)) { copy('/var/cache/phoronix-test-suite/openbenchmarking.org/' . $qualified_identifier . '.zip', $file); } else if(PTS_IS_CLIENT && $test_suite === false) { trigger_error('Network support is needed to obtain ' . $qualified_identifier . ' data.' . PHP_EOL, E_USER_ERROR); return false; } } if(!is_file(PTS_TEST_SUITE_PATH . $qualified_identifier . '/suite-definition.xml') && ($hash_check == null || (is_file($file) && sha1_file($file) == $hash_check))) { // extract it pts_file_io::mkdir(PTS_TEST_SUITE_PATH . dirname($qualified_identifier)); pts_file_io::mkdir(PTS_TEST_SUITE_PATH . $qualified_identifier); return pts_compression::zip_archive_extract($file, PTS_TEST_SUITE_PATH . $qualified_identifier); } return false; } protected static function check_only_type_compare($check_only_type, $is_type) { return $check_only_type == false || $check_only_type === $is_type; } public static function evaluate_string_to_qualifier($supplied, $bind_version = true, $check_only_type = false) { $qualified = false; $c_repo = null; $repos = self::linked_repositories(); if(($c = strpos($supplied, '/')) !== false) { // A repository was explicitly defined $c_repo = substr($supplied, 0, $c); $test = substr($supplied, ($c + 1)); // If it's in the linked repo list it should have refreshed when starting client if(!in_array($c_repo, $repos)) { // Pull in this repository's index pts_openbenchmarking::refresh_repository_lists($repos); } $repos = array($c_repo); } else { // If it's in the linked repo list it should have refreshed when starting client $test = $supplied; } if(($c = strrpos($test, '-')) !== false) { $version = substr($test, ($c + 1)); // TODO: functionalize this and read against types.xsd if(isset($version[2]) && !isset($version[8]) && pts_strings::string_only_contains($version, (pts_strings::CHAR_NUMERIC | pts_strings::CHAR_DECIMAL))) { $test = substr($test, 0, $c); } else { $version = null; } } else { $version = null; } foreach($repos as $repo) { if($repo == 'local') { if(self::check_only_type_compare($check_only_type, 'test')) { if(is_file(PTS_TEST_PROFILE_PATH . $repo . '/' . $test . '/test-definition.xml')) { return $repo . '/' . $test; // ($bind_version ? '-' . $version : null) } else if(is_file(PTS_TEST_PROFILE_PATH . $repo . '/' . $test . '-' . $version . '/test-definition.xml')) { return $repo . '/' . $test . '-' . $version; // ($bind_version ? '-' . $version : null) } } if(self::check_only_type_compare($check_only_type, 'suite')) { if(is_file(PTS_TEST_SUITE_PATH . $repo . '/' . $test . '/suite-definition.xml')) { return $repo . '/' . $test; // ($bind_version ? '-' . $version : null) } else if(is_file(PTS_TEST_SUITE_PATH . $repo . '/' . $test . '-' . $version . '/suite-definition.xml')) { return $repo . '/' . $test . '-' . $version; // ($bind_version ? '-' . $version : null) } } } $repo_index = pts_openbenchmarking::read_repository_index($repo); if(is_array($repo_index) && isset($repo_index['tests'][$test]) && self::check_only_type_compare($check_only_type, 'test')) { // The test profile at least exists // Looking for a particular test profile version? if($version != null) { if(!in_array($version, $repo_index['tests'][$test]['versions'])) { // Grep to see if the version passed was e.g. 1.3 instead of 1.3.3 $versions = $repo_index['tests'][$test]['versions']; sort($versions); foreach(array_reverse($versions) as $check_version) { if(strstr($check_version, $version) != false) { $version = $check_version; break; } } } if(in_array($version, $repo_index['tests'][$test]['versions'])) { pts_openbenchmarking::download_test_profile($repo . '/' . $test . '-' . $version); return $repo . '/' . $test . ($bind_version ? '-' . $version : null); } } else { // Assume to use the latest version unless something else is installed $available_versions = $repo_index['tests'][$test]['versions']; $version = $available_versions[0]; // the latest version available if((pts_c::$test_flags & pts_c::is_run_process)) { // Check to see if an older version of the test profile is currently installed foreach($available_versions as $i => $v) { if(is_file(pts_client::test_install_root_path() . $repo . '/' . $test . '-' . $v . '/pts-install.xml')) { $version = $v; if($i > 0 && (pts_c::$test_flags ^ pts_c::batch_mode)) { // It's not the latest test profile version available trigger_error($repo . '/' . $test . ': The latest test profile version available for upgrade is ' . $available_versions[0] . ' but version ' . $version . ' is the latest currently installed.', E_USER_WARNING); } break; } } } pts_openbenchmarking::download_test_profile($repo . '/' . $test . '-' . $version); return $repo . '/' . $test . ($bind_version ? '-' . $version : null); } } if(is_array($repo_index) && isset($repo_index['suites'][$test]) && self::check_only_type_compare($check_only_type, 'suite')) { // The test profile at least exists // Looking for a particular test profile version? if($version != null) { if(!in_array($version, $repo_index['suites'][$test]['versions'])) { // Grep to see if the version passed was e.g. 1.3 instead of 1.3.3 $versions = $repo_index['suites'][$test]['versions']; sort($versions); foreach(array_reverse($versions) as $check_version) { if(strstr($check_version, $version) != false) { $version = $check_version; break; } } } if(in_array($version, $repo_index['suites'][$test]['versions'])) { pts_openbenchmarking::download_test_suite($repo . '/' . $test . '-' . $version); return $repo . '/' . $test . ($bind_version ? '-' . $version : null); } } else { // Assume to use the latest version $version = array_shift($repo_index['suites'][$test]['versions']); pts_openbenchmarking::download_test_suite($repo . '/' . $test . '-' . $version); return $repo . '/' . $test . ($bind_version ? '-' . $version : null); } } } return false; } public static function upload_test_result(&$object) { return pts_openbenchmarking_client::upload_test_result($object); } } ?> phoronix-test-suite/pts-core/commands/copy_run_in_result_file.php0000644000175000017500000000432112151406254025605 0ustar michaelmichael. */ class copy_run_in_result_file implements pts_option_interface { const doc_section = 'Result Management'; const doc_description = 'This option is used if you wish to change an existing test run within a saved results file.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function run($r) { $result = $r[0]; $result_file = new pts_result_file($result); $result_file_identifiers = $result_file->get_system_identifiers(); $copy_identifier = pts_user_io::prompt_text_menu('Select the test run to copy', $result_file_identifiers); $copy_identifier_new = pts_user_io::prompt_user_input('Enter the new identifier of the copied run'); $merge_selects = array(); foreach($result_file_identifiers as $identifier) { $this_merge_select = new pts_result_merge_select($result, $identifier); array_push($merge_selects, $this_merge_select); if($identifier == $copy_identifier) { $this_merge_select = new pts_result_merge_select($result, $identifier); $this_merge_select->rename_identifier($copy_identifier_new); array_push($merge_selects, $this_merge_select); } } $extract_result = pts_merge::merge_test_results_array($merge_selects); pts_client::save_test_result($r[0] . '/composite.xml', $extract_result); pts_client::display_web_page(PTS_SAVE_RESULTS_PATH . $r[0] . '/index.html'); } } ?> phoronix-test-suite/pts-core/commands/dump_openbenchmarking_indexes.php0000644000175000017500000000357212206661441026753 0ustar michaelmichael. */ class dump_openbenchmarking_indexes implements pts_option_interface { public static function run($r) { echo PHP_EOL . 'OpenBenchmarking.org Repositories:' . PHP_EOL . PHP_EOL; foreach(pts_openbenchmarking::linked_repositories() as $repo) { if($repo == 'local') { // Skip local since it's a fake repository continue; } $repo_index = pts_openbenchmarking::read_repository_index($repo); $generated_time = date('F d H:i', $repo_index['main']['generated']); $tab = ' '; foreach(array('tests', 'suites') as $t) { echo PHP_EOL . str_repeat('=', 40) . PHP_EOL . strtoupper($repo . ' ' . $t) . PHP_EOL . 'Generated: ' . $generated_time . PHP_EOL . str_repeat('=', 40) . PHP_EOL . PHP_EOL; foreach($repo_index[$t] as $identifier => $test) { echo 'Identifier: ' . $identifier . PHP_EOL; foreach($test as $i => $j) { echo sprintf('%-22ls', $i) . ': '; if(is_array($j)) { echo implode(', ', $j); } else { echo $j; } echo PHP_EOL; } echo PHP_EOL; } } } } } ?> phoronix-test-suite/pts-core/commands/remove_from_result_file.php0000644000175000017500000000520312165556557025622 0ustar michaelmichael. */ class remove_from_result_file implements pts_option_interface { const doc_section = 'Result Management'; const doc_description = 'This option is used if there is a set of test results you wish to remove/delete from a saved results file. The user must specify a saved results file and then they will be prompted to select the results identifier associated with the results they wish to remove.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function run($r) { $result = $r[0]; $result_file = new pts_result_file($result); $result_file_identifiers = $result_file->get_system_identifiers(); if(count($result_file_identifiers) < 2) { echo PHP_EOL . 'There are not multiple test runs in this result file.' . PHP_EOL; return false; } $remove_identifiers = explode(',', pts_user_io::prompt_text_menu('Select the test run(s) to remove', $result_file_identifiers, true)); $keep_identifiers = array(); foreach($result_file_identifiers as $identifier) { if(!in_array($identifier, $remove_identifiers)) { array_push($keep_identifiers, $identifier); } } foreach(array('test-logs', 'system-logs', 'installation-logs') as $dir_name) { foreach($remove_identifiers as $remove_identifier) { if(is_dir(PTS_SAVE_RESULTS_PATH . $r[0] . '/' . $dir_name . '/' . $remove_identifier)) { pts_file_io::delete(PTS_SAVE_RESULTS_PATH . $r[0] . '/' . $dir_name . '/' . $remove_identifier, null, true); } } } $extract_select = new pts_result_merge_select($result, $keep_identifiers); $extract_result = pts_merge::merge_test_results($extract_select); pts_client::save_test_result($r[0] . '/composite.xml', $extract_result); pts_client::display_web_page(PTS_SAVE_RESULTS_PATH . $r[0] . '/index.html'); } } ?> phoronix-test-suite/pts-core/commands/upload_test_profile.php0000644000175000017500000000732112202505240024722 0ustar michaelmichael. */ class upload_test_profile implements pts_option_interface { const doc_section = 'OpenBenchmarking.org'; const doc_description = 'This option can be used for uploading a test profile to your account on OpenBenchmarking.org. By uploading your test profile to OpenBenchmarking.org, others are then able to browse and access this test suite for easy distribution in a seamless manner by other Phoronix Test Suite clients.'; public static function run($r) { if(pts_openbenchmarking_client::user_name() == false) { echo PHP_EOL . 'You must first be logged into an OpenBenchmarking.org account.' . PHP_EOL; echo PHP_EOL . 'Create An Account: http://openbenchmarking.org/'; echo PHP_EOL . 'Log-In Command: phoronix-test-suite openbenchmarking-setup' . PHP_EOL . PHP_EOL; return false; } foreach(pts_types::identifiers_to_test_profile_objects($r, true, true) as $test_profile) { // validate_test_profile if(pts_validation::validate_test_profile($test_profile)) { pts_client::$display->generic_heading($test_profile); $zip_file = PTS_OPENBENCHMARKING_SCRATCH_PATH . $test_profile->get_identifier_base_name() . '-' . $test_profile->get_test_profile_version() . '.zip'; $zip_created = pts_compression::zip_archive_create($zip_file, pts_file_io::glob($test_profile->get_resource_dir() . '*')); if($zip_created == false) { echo PHP_EOL . 'Failed to create zip file.' . PHP_EOL; return false; } if(filesize($zip_file) > 104857) { echo PHP_EOL . 'The test profile package is too big.' . PHP_EOL; return false; } $commit_description = pts_user_io::prompt_user_input('Enter a test commit description', false); echo PHP_EOL; $server_response = pts_openbenchmarking::make_openbenchmarking_request('upload_test_profile', array( 'tp_identifier' => $test_profile->get_identifier_base_name(), 'tp_sha1' => sha1_file($zip_file), 'tp_zip' => base64_encode(file_get_contents($zip_file)), 'tp_zip_name' => basename($zip_file), 'commit_description' => $commit_description )); echo PHP_EOL; $json = json_decode($server_response, true); if(isset($json['openbenchmarking']['upload']['error']) && !empty($json['openbenchmarking']['upload']['error'])) { echo 'ERROR: ' . $json['openbenchmarking']['upload']['error'] . PHP_EOL; } if(isset($json['openbenchmarking']['upload']['id']) && !empty($json['openbenchmarking']['upload']['id'])) { echo 'Command: phoronix-test-suite benchmark ' . $json['openbenchmarking']['upload']['id'] . PHP_EOL; } if(isset($json['openbenchmarking']['upload']['url']) && !empty($json['openbenchmarking']['upload']['url'])) { pts_openbenchmarking::refresh_repository_lists(null, true); echo 'URL: ' . $json['openbenchmarking']['upload']['url'] . PHP_EOL; } echo PHP_EOL; // TODO: chmod +x the .sh files, appropriate permissions elsewhere unlink($zip_file); } } } } ?> phoronix-test-suite/pts-core/commands/result_file_to_text.php0000644000175000017500000000532512033154063024751 0ustar michaelmichael. */ class result_file_to_text implements pts_option_interface { const doc_section = 'Result Management'; const doc_description = 'This option will read a saved test results file and output the system hardware and software information to the terminal. The test results are also outputted.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function run($r) { $result_file = new pts_result_file($r[0]); $result_output = null; $result_output .= $result_file->get_title() . PHP_EOL; $result_output .= $result_file->get_description() . PHP_EOL . PHP_EOL . PHP_EOL; $system_identifiers = $result_file->get_system_identifiers(); $system_hardware = $result_file->get_system_hardware(); $system_software = $result_file->get_system_software(); for($i = 0; $i < count($system_identifiers); $i++) { $result_output .= $system_identifiers[$i] . ': ' . PHP_EOL . PHP_EOL; $result_output .= "\t" . $system_hardware[$i] . PHP_EOL . PHP_EOL . "\t" . $system_software[$i] . PHP_EOL . PHP_EOL; } foreach($result_file->get_result_objects() as $result_object) { $result_output .= trim($result_object->test_profile->get_title() . ' ' . $result_object->test_profile->get_app_version() . PHP_EOL . $result_object->get_arguments_description()); if($result_object->test_profile->get_result_scale() != null) { $result_output .= PHP_EOL . ' ' . $result_object->test_profile->get_result_scale(); } foreach($result_object->test_result_buffer->get_buffer_items() as $buffer_item) { $result_output .= PHP_EOL . ' ' . $buffer_item->get_result_identifier() . ': ' . $buffer_item->get_result_value(); } $result_output .= PHP_EOL . PHP_EOL; } /* $file = 'SAVE_TO'; if(substr($file, -4) != '.txt') { $file .= '.txt'; } file_put_contents($file, $result_output); */ echo $result_output; } } ?> phoronix-test-suite/pts-core/commands/extract_from_result_file.php0000644000175000017500000000477212177307372026001 0ustar michaelmichael. */ class extract_from_result_file implements pts_option_interface { const doc_section = 'Result Management'; const doc_description = 'This option will extract a single set of test results from a saved results file that contains multiple test results that have been merged. The user is the prompted to specify a new result file name and select which result identifier to extract.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function run($args) { $result = $args[0]; $result_file = new pts_result_file($result); $result_file_identifiers = $result_file->get_system_identifiers(); if(count($result_file_identifiers) < 2) { echo PHP_EOL . 'There are not multiple test runs in this result file.' . PHP_EOL; return false; } $extract_identifiers = pts_strings::comma_explode(pts_user_io::prompt_text_menu('Select the test run(s) to extract', $result_file_identifiers, true)); $extract_selects = array(); foreach($extract_identifiers as $extract_identifier) { array_push($extract_selects, new pts_result_merge_select($result, $extract_identifier)); } do { echo PHP_EOL . 'Enter new result file to extract to: '; $extract_to = pts_user_io::read_user_input(); $extract_to = pts_test_run_manager::clean_save_name($extract_to); } while(empty($extract_to) || pts_result_file::is_test_result_file($extract_to)); $extract_result = call_user_func_array(array('pts_merge', 'merge_test_results'), $extract_selects); pts_client::save_test_result($extract_to . '/composite.xml', $extract_result); pts_client::display_web_page(PTS_SAVE_RESULTS_PATH . $extract_to . '/index.html'); } } ?> phoronix-test-suite/pts-core/commands/dump_documentation.php0000644000175000017500000002756612036041215024574 0ustar michaelmichael. */ class dump_documentation implements pts_option_interface { public static function run($r) { if(is_file('/usr/share/php/fpdf/fpdf.php')) { include_once('/usr/share/php/fpdf/fpdf.php'); } else { echo PHP_EOL . 'The FPDF library must be installed.' . PHP_EOL . PHP_EOL; return; } $pdf = new pts_pdf_template(pts_title(false), 'Test Client Documentation'); $html_doc = new pts_html_template(pts_title(false), 'Test Client Documentation'); $pdf->AddPage(); $pdf->Image(PTS_CORE_STATIC_PATH . 'images/pts-308x160.png', 69, 85, 73, 38, 'PNG', 'http://www.phoronix-test-suite.com/'); $pdf->Ln(120); $pdf->WriteStatement('www.phoronix-test-suite.com', 'C', 'http://www.phoronix-test-suite.com/'); $pdf->Ln(15); $pdf->WriteBigHeaderCenter(pts_title(true)); $pdf->WriteHeaderCenter('User Manual'); //$pdf->WriteText($result_file->get_description()); $pts_options = pts_documentation::client_commands_array(); // Write the test options HTML $dom = new DOMDocument(); $html = $dom->createElement('html'); $dom->appendChild($html); $head = $dom->createElement('head'); $title = $dom->createElement('title', 'User Options'); $head->appendChild($title); $html->appendChild($head); $body = $dom->createElement('body'); $html->appendChild($body); $p = $dom->createElement('p', 'The following options are currently supported by the Phoronix Test Suite client. A list of available options can also be found by running '); $em = $dom->createElement('em', 'phoronix-test-suite help.'); $p->appendChild($em); $phr = $dom->createElement('hr'); $p->appendChild($phr); $body->appendChild($p); foreach($pts_options as $section => &$contents) { if(empty($contents)) { continue; } $header = $dom->createElement('h1', $section); $body->appendChild($header); sort($contents); foreach($contents as &$option) { $sub_header = $dom->createElement('h3', $option[0]); $em = $dom->CreateElement('em', ' ' . implode(' ', $option[1])); $sub_header->appendChild($em); $body->appendChild($sub_header); $p = $dom->createElement('p', $option[2]); $body->appendChild($p); } } $dom->saveHTMLFile(PTS_PATH . 'documentation/stubs/00_user_options.html'); // Write the module options HTML $dom = new DOMDocument(); $html = $dom->createElement('html'); $dom->appendChild($html); $head = $dom->createElement('head'); $title = $dom->createElement('title', 'Module Options'); $head->appendChild($title); $html->appendChild($head); $body = $dom->createElement('body'); $html->appendChild($body); $p = $dom->createElement('p', 'The following list is the modules included with the Phoronix Test Suite that are intended to extend the functionality of pts-core. Some of these options have commands that can be run directly in a similiar manner to the other Phoronix Test Suite user commands. Some modules are just meant to be loaded directly by adding the module name to the LoadModules tag in ~/.phoronix-test-suite/user-config.xml or via the PTS_MODULES environmental variable. A list of available modules is also available by running '); $em = $dom->createElement('em', 'phoronix-test-suite list-modules.'); $p->appendChild($em); $phr = $dom->createElement('hr'); $p->appendChild($phr); $body->appendChild($p); foreach(pts_module_manager::available_modules(true) as $module) { pts_module_manager::load_module($module); $header = $dom->createElement('h2', pts_module_manager::module_call($module, 'module_name')); $body->appendChild($header); $desc = $dom->createElement('p', pts_module_manager::module_call($module, 'module_description')); $body->appendChild($desc); $all_options = pts_module_manager::module_call($module, 'user_commands'); if(count($all_options) > 0) { // $sub_header = $dom->createElement('h3', 'Module Commands'); // $body->appendChild($sub_header); foreach($all_options as $key => $option) { $p = $dom->createElement('p', 'phoronix-test-suite ' . $module . '.' . str_replace('_', '-', $key)); $body->appendChild($p); } } $vars = pts_module_manager::module_call($module, 'module_environmental_variables'); if(is_array($vars) && count($vars) > 0) { $p = $dom->createElement('p', 'This module utilizes the following environmental variables: ' . implode(', ', $vars) . '.'); $body->appendChild($p); } } $dom->saveHTMLFile(PTS_PATH . 'documentation/stubs/00_zmodule_options.html'); // Write the external dependencies HTML $dom = new DOMDocument(); $html = $dom->createElement('html'); $dom->appendChild($html); $head = $dom->createElement('head'); $title = $dom->createElement('title', 'External Dependencies'); $head->appendChild($title); $html->appendChild($head); $body = $dom->createElement('body'); $html->appendChild($body); $p = $dom->createElement('p', 'The Phoronix Test Suite has a feature known as "External Dependencies" where the Phoronix Test Suite can attempt to automatically install some of the test-specific dependencies on supported distributions. If running on a distribution where there is currently no External Dependencies profile, the needed package name(s) are listed for manual installation.'); $body->appendChild($p); $p = $dom->createElement('p', 'Below are a list of the operating systems that currently have external dependencies support within the Phoronix Test Suite for the automatic installation of needed test files.'); $body->appendChild($p); $phr = $dom->createElement('hr'); $p->appendChild($phr); $exdep_generic_parser = new pts_exdep_generic_parser(); $vendors = array_merge($exdep_generic_parser->get_vendor_aliases_formatted(), $exdep_generic_parser->get_vendors_list_formatted()); sort($vendors); $ul = $dom->createElement('ul'); $p->appendChild($ul); foreach($vendors as $vendor) { $li = $dom->createElement('li', $vendor); $p->appendChild($li); } $dom->saveHTMLFile(PTS_PATH . 'documentation/stubs/02_external_dependencies.html'); // Write the virtual suites HTML $dom = new DOMDocument(); $html = $dom->createElement('html'); $dom->appendChild($html); $head = $dom->createElement('head'); $title = $dom->createElement('title', 'Virtual Test Suites'); $head->appendChild($title); $html->appendChild($head); $body = $dom->createElement('body'); $html->appendChild($body); $p = $dom->createElement('p', 'Virtual test suites are not like a traditional test suite defined by the XML suite specification. Virtual test suites are dynamically generated in real-time by the Phoronix Test Suite client based upon the specified test critera. Virtual test suites can automatically consist of all test profiles that are compatible with a particular operating system or test profiles that meet other critera. When running a virtual suite, the OpenBenchmarking.org repository of the test profiles to use for generating the dynamic suite must be prefixed. '); $body->appendChild($p); $p = $dom->createElement('p', 'Virtual test suites can be installed and run just like a normal XML test suite and shares nearly all of the same capabilities. However, when running a virtual suite, the user will be prompted to input any user-configuration options for needed test profiles just as they would need to do if running the test individually. When running a virtual suite, the user also has the ability to select individual tests within the suite to run or to run all of the contained test profiles. Virtual test suites are also only supported for an OpenBenchmarking.org repository if there is no test profile or test suite of the same name in the repository. Below is a list of common virtual test suites for the main Phoronix Test Suite repository, but the dynamic list of available virtual test suites based upon the enabled repositories is available by running '); $em = $dom->createElement('em', 'phoronix-test-suite list-available-virtual-suites.'); $p->appendChild($em); $phr = $dom->createElement('hr'); $p->appendChild($phr); $body->appendChild($p); foreach(pts_virtual_test_suite::available_virtual_suites() as $virtual_suite) { $sub_header = $dom->createElement('h3', $virtual_suite->get_title()); $em = $dom->CreateElement('em', ' ' . $virtual_suite->get_identifier()); $sub_header->appendChild($em); $body->appendChild($sub_header); $p = $dom->createElement('p', $virtual_suite->get_description()); $body->appendChild($p); } $dom->saveHTMLFile(PTS_PATH . 'documentation/stubs/55_virtual_suites.html'); // Load the HTML documentation foreach(pts_file_io::glob(PTS_PATH . 'documentation/stubs/*_*.html') as $html_file) { $pdf->html_to_pdf($html_file); $html_doc->html_to_html($html_file); } if(!is_writable(PTS_PATH . 'documentation/')) { echo PHP_EOL . 'Not writable: ' . PTS_PATH . 'documentation/'; } else { $pdf_file = PTS_PATH . 'documentation/phoronix-test-suite.pdf'; $pdf->Output($pdf_file); $html_doc->Output(PTS_PATH . 'documentation/phoronix-test-suite.html'); echo PHP_EOL . 'Saved To: ' . $pdf_file . PHP_EOL . PHP_EOL; // Also re-generate the man page $man_page = '.TH phoronix-test-suite 1 "www.phoronix-test-suite.com" "' . PTS_VERSION . '"' . PHP_EOL . '.SH NAME' . PHP_EOL; $man_page .= 'phoronix-test-suite \- The Phoronix Test Suite is an extensible open-source platform for performing testing and performance evaluation.' . PHP_EOL; $man_page .= '.SH SYNOPSIS' . PHP_EOL . '.B phoronix-test-suite [options]' . PHP_EOL . '.br' . PHP_EOL . '.B phoronix-test-suite benchmark [test | suite]' . PHP_EOL; $man_page .= '.SH DESCRIPTION' . PHP_EOL . pts_documentation::basic_description() . PHP_EOL; $man_page .= '.SH OPTIONS' . PHP_EOL . '.TP' . PHP_EOL; foreach($pts_options as $section => &$contents) { if(empty($contents)) { continue; } $man_page .= '.SH ' . strtoupper($section) . PHP_EOL; sort($contents); foreach($contents as &$option) { $man_page .= '.B ' . trim($option[0] . ' ' . (!empty($option[1]) && is_array($option[1]) ? implode(' ', $option[1]) : null)) . PHP_EOL . $option[2] . PHP_EOL . '.TP' . PHP_EOL; } } $man_page .= '.SH SEE ALSO' . PHP_EOL . '.B Websites:' . PHP_EOL . '.br' . PHP_EOL . 'http://www.phoronix-test-suite.com/' . PHP_EOL . '.br' . PHP_EOL . 'http://commercial.phoronix-test-suite.com/' . PHP_EOL . '.br' . PHP_EOL . 'http://www.openbenchmarking.org/' . PHP_EOL . '.br' . PHP_EOL . 'http://www.phoronix.com/' . PHP_EOL . '.br' . PHP_EOL . 'http://www.phoronix.com/forums/' . PHP_EOL; $man_page .= '.SH AUTHORS' . PHP_EOL . 'Copyright 2008 - ' . date('Y') . ' by Phoronix Media, Michael Larabel.' . PHP_EOL . '.TP' . PHP_EOL; file_put_contents(PTS_PATH . 'documentation/man-pages/phoronix-test-suite.1', $man_page); } // simple README $readme = 'Phoronix Test Suite ' . PTS_VERSION . ' ' . PHP_EOL . PHP_EOL; $readme .= pts_documentation::basic_description() . PHP_EOL . PHP_EOL; $readme .= pts_file_io::file_get_contents(PTS_PATH . 'documentation/stubs/readme-basics.txt') . PHP_EOL . PHP_EOL; $readme = wordwrap($readme, 80, PHP_EOL); file_put_contents(PTS_PATH . 'README', $readme); } } ?> phoronix-test-suite/pts-core/commands/auto_compare.php0000644000175000017500000001601612035103307023340 0ustar michaelmichael. */ class auto_compare implements pts_option_interface { const doc_section = 'Testing'; const doc_description = 'This option will autonomously determine the most relevant test(s) to run for any selected sub-system(s). The tests to run are determined via OpenBenchmarking.org integration with the global results pool. Related test results from OpenBenchmarking.org are also merged to provide a straight-forward and effective means of carrying out a system comparison. If wishing to find comparable results for any particular test profile(s), simply pass the test profile names as additional arguments to this command.'; public static function invalid_command($passed_args = null) { pts_tests::invalid_command_helper($passed_args); } public static function run($r) { $compare_tests = array(); $compare_subsystems = array(); foreach($r as $test_object) { $test_object = pts_types::identifier_to_object($test_object); if($test_object instanceof pts_test_profile) { array_push($compare_tests, $test_object->get_identifier(false)); if(!isset($compare_subsystems[$test_object->get_test_hardware_type()])) { $compare_subsystems[$test_object->get_test_hardware_type()] = 1; } else { $compare_subsystems[$test_object->get_test_hardware_type()] += 1; } } } if(empty($compare_tests)) { $subsystem_under_test = pts_user_io::prompt_text_menu('Sub-System To Test', array('Processor', 'Graphics', 'Disk')); } else { arsort($compare_subsystems); $compare_subsystems = array_keys($compare_subsystems); $subsystem_under_test = array_shift($compare_subsystems); } $system_info = array_merge(phodevi::system_hardware(false), phodevi::system_software(false)); $to_include = array(); $to_exclude = array(); if(isset($system_info[$subsystem_under_test])) { $compare_component = $system_info[$subsystem_under_test]; } else { return; } switch($subsystem_under_test) { case 'Processor': self::system_component_to_format($system_info, $to_include, array('OS', 'Compiler', 'Kernel', 'Motherboard'), true); break; case 'Graphics': self::system_component_to_format($system_info, $to_include, array('OS', 'Display Driver', 'OpenGL', 'Processor', 'Kernel', 'Desktop'), true); break; case 'OS': self::system_component_to_format($system_info, $to_include, array('Processor', 'Motherboard', 'Graphics', 'Disk'), true); self::system_component_to_format($system_info, $to_exclude, array('OS')); break; case 'Disk': self::system_component_to_format($system_info, $to_include, array('Processor', 'OS', 'Chipset', 'Motherboard', 'Kernel'), true); break; } $payload = array( 'subsystem_under_test' => $subsystem_under_test, 'component_under_test' => $compare_component, 'include_components' => implode(',', $to_include), 'exclude_components' => implode(',', $to_exclude), 'include_tests' => implode(',', $compare_tests), ); echo PHP_EOL . 'Querying test data from OpenBenchmarking.org...' . PHP_EOL; $json = pts_openbenchmarking::make_openbenchmarking_request('auto_generate_comparison', $payload); $json = json_decode($json, true); if(isset($json['auto_compare']['public_ids']) && isset($json['auto_compare']['count']) && $json['auto_compare']['count'] > 0) { echo 'Found ' . $json['auto_compare']['count'] . ' comparable results on OpenBenchmarking.org with a ' . $json['auto_compare']['accuracy'] . '% accuracy.' . PHP_EOL; $compare_results = array(); foreach($json['auto_compare']['public_ids'] as $public_id) { $result_xml = pts_openbenchmarking::clone_openbenchmarking_result($public_id, true); if($result_xml) { $result_file = new pts_result_file($result_xml); $result_objects = $result_file->get_result_objects(); foreach($result_objects as $i => &$result_object) { if(!empty($compare_tests)) { if(!in_array($result_object->test_profile->get_identifier(false), $compare_tests)) { unset($result_objects[$i]); } } else if($result_object->test_profile->get_test_hardware_type() != $subsystem_under_test) { unset($result_objects[$i]); } } if(count($result_objects) == 0) { continue; } $result_file->override_result_objects($result_objects); array_push($compare_results, $result_file); } } if(count($compare_results) > 0) { $result_xml = pts_merge::merge_test_results_array($compare_results); if(count($compare_results) > 2) { $result_file = new pts_result_file($result_xml); $result_objects = $result_file->get_result_objects(); $system_count = $result_file->get_system_count(); $result_count = count($result_objects); $result_match_count = array(); if($result_count > 3) { foreach($result_objects as $i => &$result_object) { $result_match_count[$i] = $result_object->test_result_buffer->get_count(); } arsort($result_match_count); $biggest_size = pts_arrays::first_element($result_match_count); if($biggest_size == $system_count || $biggest_size > 3) { foreach($result_match_count as $key => $value) { if($value < 2) { unset($result_objects[$key]); } } } $result_file->override_result_objects($result_objects); $result_xml = pts_merge::merge_test_results_array(array($result_file)); } } pts_client::save_test_result('auto-comparison/composite.xml', $result_xml); } } pts_test_installer::standard_install(array('auto-comparison')); pts_test_run_manager::standard_run(array('auto-comparison')); } protected static function system_component_to_format(&$system_info, &$to_array, $component_types, $allow_trim_extra = false) { foreach($component_types as $component_type) { if(isset($system_info[$component_type])) { $value = pts_strings::trim_search_query($system_info[$component_type]); if($value != null) { if($allow_trim_extra && !isset($to_array[2])) { $value_r = explode(' ', str_replace('-', ' ', $value)); array_pop($value_r); array_push($to_array, $component_type . ':' . implode(' ', $value_r)); } array_push($to_array, $component_type . ':' . $value); } } } } } ?> phoronix-test-suite/pts-core/commands/list_recommended_tests.php0000664000175000017500000000451612034664040025432 0ustar michaelmichael. */ class list_recommended_tests implements pts_option_interface { const doc_section = 'OpenBenchmarking.org'; const doc_description = 'This option will list recommended test profiles for benchmarking sorted by hardware sub-system. The recommended tests are determined via querying OpenBenchmarking.org and determining the most popular tests for a given environment based upon the number of times a test profile has been downloaded, the number of test results available on OpenBenchmarking.org for a given test profile, the age of the test profile, and other weighted factors.'; public static function run($r) { pts_client::$display->generic_heading('Recommended OpenBenchmarking.org Test Profiles'); $test_count = 0; $recommendation_index = pts_openbenchmarking::make_openbenchmarking_request('recommended_tests_index'); $recommendation_index = json_decode($recommendation_index, true); foreach($recommendation_index['recommended_tests'] as $subsystem => $tests) { pts_client::$display->generic_heading($subsystem . ' Tests'); foreach($tests as $test) { echo sprintf('%-32ls - %-35ls', $test['test_profile'], $test['title']) . PHP_EOL; } $test_count++; } if($test_count == 0) { echo PHP_EOL . 'No tests found. Please check that you have Internet connectivity to download test profile data from OpenBenchmarking.org. The Phoronix Test Suite has documentation on configuring the network setup, proxy settings, and PHP network options. Please contact Phoronix Media if you continuing to experience problems.' . PHP_EOL . PHP_EOL; } } } ?> phoronix-test-suite/pts-core/commands/list_available_suites.php0000644000175000017500000000467612200006115025233 0ustar michaelmichael. */ class list_available_suites implements pts_option_interface { const doc_section = 'Information'; const doc_description = 'This option will list all test suites that are available from the enabled OpenBenchmarking.org repositories.'; public static function command_aliases() { return array('list_suites'); } public static function run($r) { $available_suites = pts_openbenchmarking::available_suites(false); pts_client::$display->generic_heading('Available Suites'); if(count($available_suites) > 0) { $has_partially_supported_suite = false; foreach($available_suites as $identifier) { $suite_info = new pts_test_suite($identifier); $partially_supported = $suite_info->is_supported() == 1; if(!$has_partially_supported_suite && $partially_supported) { $has_partially_supported_suite = true; } if($suite_info->is_supported()) { $identifier_prefix = $partially_supported ? '*' : ' '; if($suite_info->get_title() != null) { echo sprintf('%-34ls - %-32ls %s' . PHP_EOL, $identifier_prefix . ' ' . $identifier, $suite_info->get_title(), $suite_info->get_suite_type()); } } } echo PHP_EOL; if($has_partially_supported_suite) { echo '* Indicates a partially supported suite.' . PHP_EOL . PHP_EOL; } } else { echo PHP_EOL . 'No suites found. Please check that you have Internet connectivity to download test suite data from OpenBenchmarking.org. The Phoronix Test Suite has documentation on configuring the network setup, proxy settings, and PHP network options. Please contact Phoronix Media if you continuing to experience problems.' . PHP_EOL . PHP_EOL; } } } ?> phoronix-test-suite/pts-core/commands/openbenchmarking_refresh.php0000644000175000017500000000261712200005116025705 0ustar michaelmichael. */ class openbenchmarking_refresh implements pts_option_interface { const doc_section = 'OpenBenchmarking.org'; const doc_description = 'This option is used for refreshing the stored OpenBenchmarking.org repostory information and other data. The Phoronix Test Suite will automatically refresh this data every three days or when other thresholds are exceeded, but this command can be used to manually refresh/updates the data.'; public static function run($r) { echo PHP_EOL . 'Refreshing OpenBenchmarking.org Lists' . PHP_EOL . PHP_EOL; pts_openbenchmarking::refresh_repository_lists(null, true); } } ?> phoronix-test-suite/pts-core/commands/list_unsupported_tests.php0000644000175000017500000000353712200005715025531 0ustar michaelmichael. */ class list_unsupported_tests implements pts_option_interface { const doc_section = 'Information'; const doc_description = 'This option will list all available test profiles that are available from the enabled OpenBenchmarking.org repositories but are NOT SUPPORTED on the given hardware/software platform. This is mainly a debugging option for those looking for test profiles to potentially port to new platforms, etc.'; public static function run($r) { pts_client::$display->generic_heading('Unsupported Tests'); foreach(pts_openbenchmarking::available_tests() as $identifier) { $unsupported = false; $test_profile = new pts_test_profile($identifier); if($test_profile->is_test_architecture_supported() == false) { $unsupported = 'UNSUPPORTED ARCHITECTURE'; } else if($test_profile->is_test_platform_supported() == false) { $unsupported = 'UNSUPPORTED PLATFORM'; } if($unsupported) { echo sprintf('%-28ls - %-30ls %-9ls', $identifier, $unsupported, $repo_index['tests'][$id]['test_type']) . PHP_EOL; } } } } ?> phoronix-test-suite/pts-core/commands/build_suite.php0000644000175000017500000000742112200005766023176 0ustar michaelmichael. */ class build_suite implements pts_option_interface { const doc_section = 'Other'; const doc_description = 'This option will guide the user through the process of generating their own test suite, which they can then run. Optionally, passed as arguments can be the test(s) or suite(s) to add to the suite to be created, instead of being prompted through the process.'; public static function run($r) { pts_client::$display->generic_heading('Test Suite Creation'); $suite_name = pts_user_io::prompt_user_input('Enter name of suite'); $suite_test_type = pts_user_io::prompt_text_menu('Select test type', pts_types::subsystem_targets()); $suite_maintainer = pts_user_io::prompt_user_input('Enter suite maintainer name'); $suite_description = pts_user_io::prompt_user_input('Enter suite description'); $possible_suites = pts_openbenchmarking::available_suites(); $possible_tests = pts_openbenchmarking::available_tests(); $suite_writer = new pts_test_suite_writer(); $suite_writer->add_suite_information($suite_name, '1.0.0', $suite_maintainer, $suite_test_type, $suite_description); foreach($r as $test_object) { $test_object = pts_types::identifier_to_object($test_object); if($test_object instanceof pts_test_profile) { list($args, $description) = pts_test_run_options::prompt_user_options($test_object); for($i = 0; $i < count($args); $i++) { // Not binding the test profile version to this suite, otherwise change false to true $suite_writer->add_to_suite($test_object->get_identifier(false), $args[$i], $description[$i]); } } else if($test_object instanceof pts_test_suite) { $suite_writer->add_to_suite($test_object->get_identifier(), null, null); } } $input_option = null; do { switch($input_option) { case 'Add Test': $test_to_add = pts_user_io::prompt_text_menu('Enter test name', $possible_tests); $test_profile = new pts_test_profile($test_to_add); list($args, $description) = pts_test_run_options::prompt_user_options($test_profile); for($i = 0; $i < count($args); $i++) { $suite_writer->add_to_suite($test_to_add, $args[$i], $description[$i]); } break; case 'Add Sub-Suite': $suite_to_add = pts_user_io::prompt_text_menu('Enter test suite', $possible_suites); $suite_writer->add_to_suite($suite_to_add, null, null); break; } echo PHP_EOL . 'Available Options:' . PHP_EOL; $input_option = pts_user_io::prompt_text_menu('Select next operation', array('Add Test', 'Add Sub-Suite', 'Save & Exit')); } while($input_option != 'Save & Exit'); $suite_identifier = pts_test_run_manager::clean_save_name($suite_name); $save_to = PTS_TEST_SUITE_PATH . 'local/' . $suite_identifier . '/suite-definition.xml'; mkdir(dirname($save_to)); if($suite_writer->save_xml($save_to) != false) { echo PHP_EOL . PHP_EOL . 'Saved To: ' . $save_to . PHP_EOL . 'To run this suite, type: phoronix-test-suite benchmark ' . $suite_identifier . PHP_EOL . PHP_EOL; } } } ?> phoronix-test-suite/pts-core/commands/interactive.php0000644000175000017500000002257312200006766023211 0ustar michaelmichael. */ class interactive implements pts_option_interface { const doc_section = 'System'; const doc_description = 'A simple text-driven interactive interface to the Phoronix Test Suite.'; public static function run($r) { $is_moscow = pts_flags::os_identifier_hash() == 'b28d6a7148b34595c5b397dfcf5b12ac7932b3dc'; if($is_moscow) { // Auto mount? $drives = pts_file_io::glob('/dev/sda*'); sort($drives); if(false && count($drives) > 0 && !is_dir('/media/pts-auto-mount') && is_writable('/media/')) { $last_drive = array_pop($drives); echo PHP_EOL . 'Attempting to auto-mount drive: ' . $last_drive . PHP_EOL; mkdir('/media/pts-auto-mount'); exec('mount ' . $last_drive . ' /media/pts-auto-mount'); putenv('PTS_TEST_INSTALL_ROOT_PATH=/media/pts-auto-mount/'); } // Auto save results $test_results_name = phodevi::read_property('motherboard', 'serial-number'); if($test_results_name == null) { $test_results_name = phodevi::read_name('motherboard'); } if($test_results_name == null) { $test_results_name = phodevi::read_property('system', 'vendor-identifier'); } putenv('TEST_RESULTS_NAME=' . str_replace(' ', null, $test_results_name)); putenv('TEST_RESULTS_IDENTIFIER=' . $test_results_name); putenv('TEST_RESULTS_DESCRIPTION=Tests using ' . phodevi::read_property('system', 'operating-system') . ' on ' . date('d F Y') . ' of ' . $test_results_name . '.'); self::select_drive_mount(); } pts_openbenchmarking::refresh_repository_lists(); pts_client::$display->generic_heading('Interactive Benchmarking'); echo 'System Hardware:' . PHP_EOL . phodevi::system_hardware(true) . (phodevi::read_property('motherboard', 'serial-number') != null ? PHP_EOL . 'System Serial Number: ' . phodevi::read_property('motherboard', 'serial-number') : null) . PHP_EOL . PHP_EOL . PHP_EOL; $reboot_on_exit = pts_flags::is_live_cd() && pts_client::user_home_directory() == '/root/'; do { $options = array( 'RUN_TEST' => 'Run A Test', 'RUN_SUITE' => 'Run A Suite [A Collection Of Tests]', 'RUN_SYSTEM_TEST' => 'Run Complex System Test', 'SHOW_INFO' => 'Show System Hardware / Software Information', 'SHOW_SENSORS' => 'Show Auto-Detected System Sensors', 'SET_RUN_COUNT' => 'Set Test Run Repetition' ); if($is_moscow) { unset($options['RUN_SUITE']); // $options['SELECT_DRIVE_MOUNT'] = 'Select Disk Drive To Use For Testing'; } if(count(pts_client::saved_test_results()) > 0) { $options['BACKUP_RESULTS_TO_USB'] = 'Backup Results To Media Storage'; } $options['EXIT'] = ($reboot_on_exit ? 'Exit & Reboot' : 'Exit'); $response = pts_user_io::prompt_text_menu('Select Task', $options, false, true); switch($response) { case 'RUN_TEST': $supported_tests = pts_openbenchmarking::available_tests(); $supported_tests = pts_types::identifiers_to_test_profile_objects($supported_tests, false, true); $longest_title_length = 0; foreach($supported_tests as $i => &$test_profile) { if($test_profile->get_title() == null || pts_test_run_manager::test_profile_system_compatibility_check($test_profile) == false) { unset($supported_tests[$i]); continue; } if($is_moscow && pts_test_install_request::test_files_available_locally($test_profile) == false) { // Don't show tests where files need to be downloaded unset($supported_tests[$i]); continue; } $longest_title_length = max($longest_title_length, strlen($test_profile->get_title())); } $t = array(); foreach($supported_tests as $i => &$test_profile) { if($test_profile instanceof pts_test_profile) { $t[$test_profile->get_identifier()] = sprintf('%-' . ($longest_title_length + 1) . 'ls - %-10ls', $test_profile->get_title(), $test_profile->get_test_hardware_type()); } } $supported_tests = $t; asort($supported_tests); $tests_to_run = pts_user_io::prompt_text_menu('Select Test', $supported_tests, true, true); $tests_to_run = explode(',', $tests_to_run); pts_test_installer::standard_install($tests_to_run); $run_manager = pts_test_run_manager::standard_run($tests_to_run, (pts_c::defaults_mode | pts_c::auto_mode)); if($run_manager != false) { pts_client::display_web_page(PTS_SAVE_RESULTS_PATH . $run_manager->get_file_name() . '/index.html', null, true, true); } break; case 'RUN_SUITE': $possible_suites = pts_openbenchmarking::available_suites(); foreach(array_map('strtolower', pts_types::subsystem_targets()) as $subsystem) { array_push($possible_suites, 'pts/' . $subsystem); } $suites_to_run = pts_user_io::prompt_text_menu('Select Suite', $possible_suites, true); foreach(explode(',', $suites_to_run) as $suite_to_run) { pts_test_installer::standard_install($suite_to_run); pts_test_run_manager::standard_run($suite_to_run, (pts_c::defaults_mode | pts_c::auto_mode)); } break; case 'SELECT_DRIVE_MOUNT': self::select_drive_mount(); break; case 'RUN_SYSTEM_TEST': pts_client::$display->generic_heading('System Test'); $system_tests = array('apache', 'c-ray', 'ramspeed', 'postmark'); pts_test_installer::standard_install($system_tests); $run_manager = pts_test_run_manager::standard_run($system_tests, (pts_c::defaults_mode | pts_c::auto_mode)); if($run_manager != false) { pts_client::display_web_page(PTS_SAVE_RESULTS_PATH . $run_manager->get_file_name() . '/index.html', null, true, true); } break; case 'SHOW_INFO': pts_client::$display->generic_heading('System Software / Hardware Information'); echo 'Hardware:' . PHP_EOL . phodevi::system_hardware(true) . PHP_EOL . PHP_EOL; echo 'Software:' . PHP_EOL . phodevi::system_software(true) . PHP_EOL . PHP_EOL; break; case 'SHOW_SENSORS': pts_client::$display->generic_heading('Detected System Sensors'); foreach(phodevi::supported_sensors() as $sensor) { echo phodevi::sensor_name($sensor) . ': ' . phodevi::read_sensor($sensor) . ' ' . phodevi::read_sensor_unit($sensor) . PHP_EOL; } break; case 'SET_RUN_COUNT': $run_count = pts_user_io::prompt_user_input('Set the minimum number of times each test should repeat', false); putenv('FORCE_TIMES_TO_RUN=' . trim($run_count)); break; case 'BACKUP_RESULTS_TO_USB': pts_client::$display->generic_heading('Backing Up Test Results'); if($is_moscow) { $drives = pts_file_io::glob('/dev/sd*'); sort($drives); if(count($drives) > 0 && is_writable('/media/')) { $select_drive = pts_user_io::prompt_text_menu('Select Drive / Partition To Save Results', $drives); echo PHP_EOL . 'Attempting to mount: ' . $select_drive . PHP_EOL; mkdir('/media/00-results-backup'); exec('mount ' . $select_drive . ' /media/00-results-backup'); } } foreach(pts_file_io::glob('/media/*') as $media_dir) { if(!is_writable($media_dir)) { echo PHP_EOL . $media_dir . ' is not writable.' . PHP_EOL; continue; } echo PHP_EOL . 'Writing Test Results To: ' . $media_dir . PHP_EOL; pts_file_io::copy(PTS_SAVE_RESULTS_PATH, $media_dir . '/'); break; } if($is_moscow && is_dir('/media/00-results-backup')) { exec('umount /media/00-results-backup'); rmdir('/media/00-results-backup'); } break; } echo PHP_EOL . PHP_EOL; } while($response != 'EXIT'); if($reboot_on_exit) { if(is_dir('/media/pts-auto-mount')) { pts_file_io::delete('/media/pts-auto-mount/pts', null, true); exec('umount /media/pts-auto-mount 2>&1'); } exec('reboot'); } } private static function select_drive_mount() { $drives = pts_file_io::glob('/dev/sd*'); if(count($drives) == 0) { echo PHP_EOL . 'No Disk Drives Found' . PHP_EOL . PHP_EOL; } else { array_push($drives, 'No HDD'); $to_mount = pts_user_io::prompt_text_menu('Select Drive / Partition To Mount', $drives); if($to_mount != 'No HDD') { echo PHP_EOL . 'Attempting to mount: ' . $to_mount . PHP_EOL; exec('umount /media/pts-auto-mount 2>&1'); pts_file_io::delete('/media/pts-auto-mount', null, true); pts_file_io::mkdir('/media/pts-auto-mount'); echo exec('mount ' . $to_mount . ' /media/pts-auto-mount'); putenv('PTS_TEST_INSTALL_ROOT_PATH=/media/pts-auto-mount/'); } else { if(is_dir('/media/pts-auto-mount')) { exec('umount /media/pts-auto-mount'); @rmdir('/media/pts-auto-mount'); } putenv('PTS_TEST_INSTALL_ROOT_PATH='); } } } } ?> phoronix-test-suite/pts-core/commands/list_available_tests.php0000644000175000017500000000524212200006012025043 0ustar michaelmichael. */ class list_available_tests implements pts_option_interface { const doc_section = 'Information'; const doc_description = 'This option will list all test profiles that are available from the enabled OpenBenchmarking.org repositories.'; public static function command_aliases() { return array('list_tests', 'list_supported_tests'); } public static function run($r) { pts_client::$display->generic_heading('Available Tests'); $test_count = 0; foreach(pts_openbenchmarking::available_tests(false) as $identifier) { $repo = substr($identifier, 0, strpos($identifier, '/')); $id = substr($identifier, strlen($repo) + 1); $repo_index = pts_openbenchmarking::read_repository_index($repo); if(!in_array(phodevi::operating_system(), $repo_index['tests'][$id]['supported_platforms']) || empty($repo_index['tests'][$id]['title'])) { // Don't show unsupported tests continue; } echo sprintf('%-30ls - %-35ls %-9ls', $identifier, $repo_index['tests'][$id]['title'], $repo_index['tests'][$id]['test_type']) . PHP_EOL; $test_count++; } foreach(pts_file_io::glob(PTS_TEST_PROFILE_PATH . 'local/*/test-definition.xml') as $path) { $test_profile = new pts_test_profile('local/' . basename(dirname($path))); if($test_profile->get_title() != null && $test_profile->is_supported(false)) { echo sprintf('%-30ls - %-35ls %-9ls', $test_profile->get_identifier(), $test_profile->get_title(), $test_profile->get_test_hardware_type()) . PHP_EOL; $test_count++; } } if($test_count == 0) { echo PHP_EOL . 'No tests found. Please check that you have Internet connectivity to download test profile data from OpenBenchmarking.org. The Phoronix Test Suite has documentation on configuring the network setup, proxy settings, and PHP network options. Please contact Phoronix Media if you continuing to experience problems.' . PHP_EOL . PHP_EOL; } } } ?> phoronix-test-suite/pts-core/commands/list_installed_suites.php0000644000175000017500000000311312200006140025251 0ustar michaelmichael. */ class list_installed_suites implements pts_option_interface { const doc_section = 'Information'; const doc_description = 'This option will list all suites that are currently installed on the system.'; public static function run($r) { $installed_suites = array(); foreach(pts_openbenchmarking::available_suites() as $suite) { $suite = new pts_test_suite($suite); if($suite->needs_updated_install() == false) { array_push($installed_suites, $suite); } } pts_client::$display->generic_heading(count($installed_suites) . ' Suites Installed'); if(count($installed_suites) > 0) { foreach($installed_suites as $identifier) { $test_suite = new pts_test_suite($identifier); echo '- ' . $test_suite->get_title() . PHP_EOL; } echo PHP_EOL; } } } ?> phoronix-test-suite/pts-core/commands/upload_result.php0000644000175000017500000000333412202227622023546 0ustar michaelmichael. */ class upload_result implements pts_option_interface { const doc_section = 'OpenBenchmarking.org'; const doc_description = 'This option is used for uploading a test result to OpenBenchmarking.org.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function command_aliases() { return array('upload', 'upload_results', 'upload_result_file'); } public static function invalid_command($passed_args = null) { pts_tests::recently_saved_results(); } public static function run($r) { $result_file = pts_types::identifier_to_object($r[0]); $upload_url = pts_openbenchmarking::upload_test_result($result_file); if($upload_url) { pts_client::display_web_page($upload_url, 'Do you want to view the results on OpenBenchmarking.org', true); } else { echo PHP_EOL . 'Results Failed To Upload.' . PHP_EOL; } } } ?> phoronix-test-suite/pts-core/commands/debug_self_test.php0000664000175000017500000000626212130645035024031 0ustar michaelmichael. */ class debug_self_test implements pts_option_interface { const doc_section = 'Other'; const doc_description = 'This option is used during the development of the Phoronix Test Suite software for testing of internal interfaces, commands, and other common code-paths. The produced numbers should only be comparable for the same version of the Phoronix Test Suite, on the same hardware/software system, conducted on the same day of testing. This isn\'t intended as any scientific benchmark but simply to stress common PHP code-paths and looking for hot areas to optimize, etc.'; 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'), // 'refresh_graphs' => 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; } } ?> phoronix-test-suite/pts-core/commands/openbenchmarking_changes.php0000644000175000017500000000622412206661377025704 0ustar michaelmichael. */ class openbenchmarking_changes implements pts_option_interface { const doc_section = 'OpenBenchmarking.org'; const doc_description = 'This option will list recent changes to test profiles of enabled OpenBenchmarking.org repositories.'; public static function run($r) { pts_client::$display->generic_heading('Recently Updated OpenBenchmarking.org Tests'); $recently_updated = array(); foreach(pts_openbenchmarking::linked_repositories() as $repo) { if($repo == 'local') { // Skip local since it's a fake repository continue; } $repo_index = pts_openbenchmarking::read_repository_index($repo); $changes[$repo] = pts_openbenchmarking_client::fetch_repository_changelog($repo); if(isset($repo_index['tests']) && is_array($repo_index['tests'])) { foreach(array_keys($repo_index['tests']) as $identifier) { if($repo_index['tests'][$identifier]['last_updated'] > (time() - (90 * 86400))) { $recently_updated[$repo . '/' . $identifier] = $repo_index['tests'][$identifier]; } } } } if(count($recently_updated) > 0) { // sort by date uasort($recently_updated, array('openbenchmarking_changes', 'compare_time_stamps')); // so that tests are shown from newest to oldest $recently_updated = array_reverse($recently_updated); $longest_identifier_length = array_keys($recently_updated); $longest_identifier_length = strlen(pts_strings::find_longest_string($longest_identifier_length)) + 1; foreach($recently_updated as $test_profile => $repo_data) { echo sprintf('%-' . $longest_identifier_length . 'ls - %-35ls', $test_profile, $repo_data['title']) . PHP_EOL; $br = explode('/', $test_profile); if(isset($changes[$br[0]]['tests'][$br[1]]['changes'])) { foreach($changes[$br[0]]['tests'][$br[1]]['changes'] as $test_profile_version => $data) { echo 'v' . $test_profile_version . ' [' . date('d M Y', $data['last_updated']) . ']' . PHP_EOL; echo ' - ' . $data['commit_description'] . PHP_EOL; } } else { echo 'Last Updated: ' . date('d F Y', $repo_data['last_updated']) . PHP_EOL; } echo PHP_EOL; // $repo_data['test_type'] } } else { echo PHP_EOL . 'No updated tests were found.' . PHP_EOL; } } protected static function compare_time_stamps($a, $b) { return $a['last_updated'] < $b['last_updated'] ? -1 : 1; } } ?> phoronix-test-suite/pts-core/commands/diagnostics.php0000644000175000017500000000322612130602407023171 0ustar michaelmichael. */ class diagnostics implements pts_option_interface { const doc_section = 'System'; const doc_description = 'This option will print information that is useful to developers when debugging problems with the Phoronix Test Suite and/or test profiles and test suites.'; public static function run($r) { foreach(pts_define(-1) as $constant => $constant_value) { echo $constant . ' = ' . $constant_value . PHP_EOL; } echo PHP_EOL . 'Variables That Can Be Used As Result Identifiers / File Names:' . PHP_EOL; foreach(pts_client::user_run_save_variables() as $var => $var_value) { echo $var . ' = ' . $var_value . PHP_EOL; } echo PHP_EOL . 'Environmental Variables (accessible via test scripts):' . PHP_EOL; foreach(pts_client::environmental_variables() as $var => $var_value) { echo $var . ' = ' . $var_value . PHP_EOL; } echo PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/openbenchmarking_login.php0000644000175000017500000000521312202501117025356 0ustar michaelmichael. */ class openbenchmarking_login implements pts_option_interface { const doc_section = 'OpenBenchmarking.org'; const doc_description = 'This option is used for controlling your Phoronix Test Suite client options for OpenBechmarking.org and syncing the client to your account.'; public static function command_aliases() { return array('openbenchmarking_setup'); } public static function run($r) { echo PHP_EOL . 'If you have not already registered for your free OpenBenchmarking.org account, you can do so at http://openbenchmarking.org/' . PHP_EOL . PHP_EOL . 'Once you have registered your account and clicked the link within the verification email, enter your log-in information below.' . PHP_EOL . PHP_EOL; echo 'User-Name: '; $username = pts_user_io::read_user_input(); echo 'Password: '; $password = pts_user_io::read_user_input(); $login_payload = array( 's_u' => $username, 's_p' => sha1($password), 's_s' => base64_encode(phodevi::system_software(true)), 's_h' => base64_encode(phodevi::system_hardware(true)) ); $login_state = pts_openbenchmarking::make_openbenchmarking_request('account_login', $login_payload); $json = json_decode($login_state, true); if(isset($json['openbenchmarking']['response']['error'])) { trigger_error($json['openbenchmarking']['response']['error'], E_USER_ERROR); pts_storage_object::remove_in_file(PTS_CORE_STORAGE, 'openbenchmarking'); } else { $openbenchmarking_payload = array( 'user_name' => $json['openbenchmarking']['account']['user_name'], 'communication_id' => $json['openbenchmarking']['account']['communication_id'], 'sav' => $json['openbenchmarking']['account']['sav'], ); pts_storage_object::set_in_file(PTS_CORE_STORAGE, 'openbenchmarking', $openbenchmarking_payload); echo PHP_EOL . PHP_EOL . 'The Account Has Been Setup.' . PHP_EOL . PHP_EOL; } } } ?> phoronix-test-suite/pts-core/commands/openbenchmarking_repositories.php0000644000175000017500000000356612206661474027027 0ustar michaelmichael. */ class openbenchmarking_repositories implements pts_option_interface { const doc_section = 'OpenBenchmarking.org'; const doc_description = 'This option will list the OpenBenchmarking.org repositories currently linked to this Phoronix Test Suite client instance.'; public static function run($r) { echo PHP_EOL . 'Linked OpenBenchmarking.org Repositories:' . PHP_EOL . PHP_EOL; foreach(pts_openbenchmarking::linked_repositories() as $repo) { if($repo == 'local') { // Skip local since it's a fake repository continue; } $repo_index = pts_openbenchmarking::read_repository_index($repo); $test_count = count($repo_index['tests']); $suite_count = count($repo_index['suites']); $generated_time = date('F d H:i', $repo_index['main']['generated']); echo sprintf(' REPO: %-20ls WEB: %-35ls' . PHP_EOL, $repo, 'http://openbenchmarking.org/user/' . $repo); echo sprintf(' LAST GENERATED: %-3ls' . PHP_EOL, $generated_time); echo sprintf(' TEST COUNT: %-3ls SUITE COUNT: %-3ls' . PHP_EOL, $test_count, $suite_count); echo PHP_EOL; } } } ?> phoronix-test-suite/pts-core/commands/refresh_graphs.php0000644000175000017500000000320312207413764023672 0ustar michaelmichael. */ class refresh_graphs implements pts_option_interface { const doc_section = 'Result Management'; const doc_description = 'This option will re-render and save all result graphs within a saved file. This option can be used when making modifications to the graphing code or its color/option configuration file and testing the changes.'; public static function command_aliases() { return array('refresh_graph'); } public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function run($r) { $identifier = $r[0]; pts_client::regenerate_graphs($identifier, 'The ' . $identifier . ' result file graphs have been refreshed.'); } public static function invalid_command($passed_args = null) { pts_tests::invalid_command_helper($passed_args); } } ?> phoronix-test-suite/pts-core/commands/webui.php0000644000175000017500000000412012023476124021775 0ustar michaelmichael. */ // chromium-browser --incognito --temp-profile --kiosk --app= class webui implements pts_option_interface { const doc_skip = true; // TODO XXX: cleanup this code before formally advertising this... const doc_section = 'Web User Interface'; const doc_description = 'Launch the Phoronix Test Suite web user-interface.'; public static function run($r) { //return false; // This won't be formally ready for PTS 4.0 Suldal if(PHP_VERSION_ID < 50400) { echo 'Running an unsupported PHP version. PHP 5.4+ is required to use this feature.' . PHP_EOL . PHP_EOL; return false; } if(!function_exists('pcntl_fork')) { echo 'PCNTL support is required to use this feature' . PHP_EOL . PHP_EOL; return false; } echo '
';
		echo 'Hardware:' . PHP_EOL . phodevi::system_hardware(true) . PHP_EOL . PHP_EOL;
		echo 'Software:' . PHP_EOL . phodevi::system_software(true) . PHP_EOL . PHP_EOL;
		echo '
'; /* $chrome = pts_client::executable_in_path('chromium-browser'); if($chrome) { $pid = pcntl_fork(); if($pid == -1) { echo 'ERROR' . PHP_EOL; } else if($pid) { shell_exec($chrome . ' --temp-profile --app=http://localhost:2300'); //pcntl_wait($status); } else { echo shell_exec(getenv('PHP_BIN') . ' -S localhost:2300 test.php'); } }*/ } } ?> phoronix-test-suite/pts-core/commands/make_download_cache.php0000644000175000017500000000611112172336533024617 0ustar michaelmichael. */ class make_download_cache implements pts_option_interface { const doc_section = 'Test Installation'; const doc_description = 'This option will create a download cache for use by the Phoronix Test Suite.'; public static function run($r) { // Generates a PTS Download Cache $dc_write_directory = null; $dc_write_directory = pts_strings::add_trailing_slash(pts_client::parse_home_directory(pts_config::read_user_config('PhoronixTestSuite/Options/Installation/CacheDirectory', PTS_DOWNLOAD_CACHE_PATH))); if($dc_write_directory == null || !is_writable($dc_write_directory)) { echo 'No writable download cache directory was found. A download cache cannot be created.' . PHP_EOL . PHP_EOL; return false; } echo PHP_EOL . 'Download Cache Directory: ' . $dc_write_directory . PHP_EOL; $xml_writer = new nye_XmlWriter(); foreach(pts_tests::installed_tests() as $test) { $test_profile = new pts_test_profile($test); $cached = false; echo PHP_EOL . 'Checking Downloads For: ' . $test . PHP_EOL; foreach(pts_test_install_request::read_download_object_list($test_profile, false) as $file) { if(is_file($dc_write_directory . $file->get_filename()) && $file->check_file_hash($dc_write_directory . $file->get_filename())) { echo ' Previously Cached: ' . $file->get_filename() . PHP_EOL; $cached = true; } else { if(is_dir($test_profile->get_install_dir())) { if(is_file($test_profile->get_install_dir() . $file->get_filename()) && $file->check_file_hash($test_profile->get_install_dir() . $file->get_filename())) { echo ' Caching: ' . $file->get_filename() . PHP_EOL; if(copy($test_profile->get_install_dir() . $file->get_filename(), $dc_write_directory . $file->get_filename())) { $cached = true; } } } } if($cached) { $xml_writer->addXmlNode('PhoronixTestSuite/DownloadCache/Package/FileName', $file->get_filename()); $xml_writer->addXmlNode('PhoronixTestSuite/DownloadCache/Package/MD5', $file->get_md5()); $xml_writer->addXmlNode('PhoronixTestSuite/DownloadCache/Package/SHA256', $file->get_sha256()); } } } $cache_xml = $xml_writer->getXML(); file_put_contents($dc_write_directory . 'pts-download-cache.xml', $cache_xml); echo PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/ob_test_profile_analyze.php0000644000175000017500000005667412000021321025565 0ustar michaelmichael. */ ini_set('memory_limit', '16192M'); class ob_test_profile_analyze implements pts_option_interface { const doc_skip = true; // TODO XXX: cleanup this code before formally advertising this... const doc_section = 'OpenBenchmarking.org'; const doc_description = 'This option is intended for test profile creators and generates a range of meta-data and other useful information that can be submitted to OpenBenchmarking.org to provide more verbose information for users of your test profiles.'; public static function run($r) { if(pts_openbenchmarking_client::user_name() == false) { echo PHP_EOL . 'You must first be logged into an OpenBenchmarking.org account.' . PHP_EOL; echo PHP_EOL . 'Create An Account: http://openbenchmarking.org/'; echo PHP_EOL . 'Log-In Command: phoronix-test-suite openbenchmarking-setup' . PHP_EOL . PHP_EOL; return false; } ini_set('memory_limit', '2048M'); foreach(pts_types::identifiers_to_test_profile_objects($r, false, true) as $test_profile) { $qualified_identifier = $test_profile->get_identifier(); // First make sure the test profile is already in the OpenBenchmarking.org database... $json = pts_openbenchmarking::make_openbenchmarking_request('is_test_profile', array('i' => $qualified_identifier)); $json = json_decode($json, true); if(!isset($json['openbenchmarking']['test']['valid']) || $json['openbenchmarking']['test']['valid'] != 'TRUE') { echo PHP_EOL . $qualified_identifier . ' must first be uploaded to OpenBenchmarking.org.' . PHP_EOL; // break; } // Set some other things... pts_client::pts_set_environment_variable('FORCE_TIMES_TO_RUN', 1); pts_client::pts_set_environment_variable('TEST_RESULTS_NAME', $test_profile->get_title() . ' Testing ' . date('Y-m-d')); pts_client::pts_set_environment_variable('TEST_RESULTS_IDENTIFIER', 'Sample Run'); pts_client::pts_set_environment_variable('TEST_RESULTS_DESCRIPTION', 1); pts_openbenchmarking_client::override_client_setting('AutoUploadResults', true); pts_openbenchmarking_client::override_client_setting('UploadSystemLogsByDefault', true); // Take screenshots pts_client::pts_set_environment_variable('SCREENSHOT_INTERVAL', 9); pts_module_manager::attach_module('timed_screenshot'); $force_ss = true; $reference_ss_file = pts_module_manager::module_call('timed_screenshot', 'take_screenshot', $force_ss); sleep(2); $apitrace = pts_file_io::glob('/usr/local/lib/*/apitrace/wrappers/glxtrace.so'); if(!empty($apitrace) && pts_client::executable_in_path('apitrace')) { $apitrace = array_shift($apitrace); putenv('LD_PRELOAD=' . $apitrace); } else { $apitrace = false; } // So for any compiling tasks they will try to use the most aggressive instructions possible putenv('CFLAGS=-march=native -O3'); putenv('CXXFLAGS=-march=native -O3'); pts_test_installer::standard_install($qualified_identifier, pts_c::force_install); pts_test_run_manager::standard_run($qualified_identifier, (pts_c::defaults_mode | pts_c::auto_mode)); if($apitrace) { putenv('LD_PRELOAD='); } if($reference_ss_file) { $reference_ss = pts_image::image_file_to_gd($reference_ss_file); unlink($reference_ss_file); $screenshots_gd = array(); $screenshots = pts_module_manager::module_call('timed_screenshot', 'get_screenshots'); var_dump($screenshots); foreach($screenshots as $ss_file) { $screenshots_gd[$ss_file] = pts_image::image_file_to_gd($ss_file); if($screenshots_gd[$ss_file] == false) { continue; } $ss_delta = pts_image::gd_image_delta_composite($reference_ss, $screenshots_gd[$ss_file], true); if(count($ss_delta) < floor(imagesx($reference_ss) * 0.56) || filesize($ss_file) > 2097152) { // If less than 56% of the pixels are changing on X, then likely not much to show off... (CLI only likely) // Or if filesize of image is beyond 2MB //echo 'dropping' . $ss_file . PHP_EOL; unset($screenshots_gd[$ss_file]); pts_file_io::unlink($ss_file); } } $ss_files = array_keys($screenshots_gd); shuffle($ss_files); // Don't upload more than 4MB worth of screenshots while(pts_file_io::array_filesize($ss_files) > (1048576 * 2)) { $f = array_pop($ss_files); unlink($f); } if(count($ss_files) > 0) { $c = 1; foreach($ss_files as $i => $file) { $new_file = dirname($file) . '/screenshot-' . $c . '.png'; rename($file, $new_file); $ss_files[$i] = $new_file; $c++; } $ss_zip_file = PTS_OPENBENCHMARKING_SCRATCH_PATH . 'screenshots-' . $test_profile->get_identifier_base_name() . '-' . $test_profile->get_test_profile_version() . '.zip'; $zip_created = pts_compression::zip_archive_create($ss_zip_file, $ss_files); if($zip_created) { echo count($ss_files) . ' screenshots captured for use.'; //'tp_sha1' => sha1_file($zip_file), //'tp_zip' => base64_encode(file_get_contents($zip_file)), } foreach($ss_files as $file) { // pts_file_io::unlink($file); } } } $test_binary = self::locate_test_profile_lead_binary($test_profile); $shared_library_dependencies = array(); $instruction_usage = array(); $gl_calls = null; if(is_executable($test_binary)) { if($apitrace) { // Find the trace... $test_binary_dir = dirname($test_binary); $trace_file = glob($test_binary_dir . '/*.trace'); if($trace_file) { echo 'Analyzing GL traces'; $trace_file = array_shift($trace_file); $gl_usage = self::analyze_apitrace_trace_glpop($trace_file); if(!empty($gl_usage)) { $gl_calls = implode(',', $gl_usage); } } } $ldd = trim(shell_exec('ldd ' . $test_binary)); foreach(explode(PHP_EOL, $ldd) as $line) { $line = explode(' => ', $line); if(count($line) == 2) { array_push($shared_library_dependencies, trim(basename($line[0]))); } } echo PHP_EOL . 'SHARED LIBRARY DEPENDENCIES: ' . PHP_EOL; print_r($shared_library_dependencies); foreach(array('core-avx-i', 'bdver2') as $march) { // So for any compiling tasks they will try to use the most aggressive instructions possible putenv('CFLAGS=-march=' . $march . ' -O3'); putenv('CXXFLAGS=-march=' . $march . ' -O3'); pts_test_installer::standard_install($qualified_identifier, pts_c::force_install); $instruction_usage[$march] = self::analyze_binary_instruction_usage($test_binary); if($instruction_usage[$march] == null) { unset($instruction_usage[$march]); } } if(!empty($instruction_usage) && count(array_unique($instruction_usage)) == 1) { $generic = array_pop($instruction_usage); $instruction_usage = array('generic' => $generic); } var_dump($instruction_usage); } else { echo PHP_EOL . $test_binary; echo PHP_EOL . 'Test binary could not be found.' . PHP_EOL; // return false; } } sleep(10); var_dump($shared_library_dependencies); var_dump($instruction_usage); var_dump($gl_calls); $server_response = pts_openbenchmarking::make_openbenchmarking_request('upload_test_meta', array( 'i' => $test_profile->get_identifier(), 'screenshots_zip' => ($ss_zip_conts = base64_encode(file_get_contents($ss_zip_file))), 'screenshots_zip_sha1' => sha1($ss_zip_conts), 'ldd_libraries' => implode(',', $shared_library_dependencies), 'opengl_calls' => $gl_calls, 'instruction_set_usage' => base64_encode(json_encode($instruction_usage)) )); var_dump($server_response); $json = json_decode($server_response, true); pts_file_io::unlink($ss_zip_file); } public static function locate_test_profile_lead_binary(&$test_profile) { $test_profile_launcher = $test_profile->get_test_executable_dir() . $test_profile->get_test_executable(); if(!is_file($test_profile_launcher)) { echo PHP_EOL . $test_profile_launcher . ' not found.' . PHP_EOL; return false; } $original_launcher_contents = file_get_contents($test_profile_launcher); $test_binary = false; if(($s = strpos($original_launcher_contents, '$LOG_FILE'))) { $launcher_contents = substr($original_launcher_contents, 0, $s); $test_binary = pts_strings::first_in_string(trim(str_replace(array(' ', ' ', 'mpirun', 'mpiexec', './'), '', substr($launcher_contents, strrpos($launcher_contents, PHP_EOL) + 1)))); } if(strpos($test_binary, '.app') && strpos($original_launcher_contents, '$LOG_FILE') != ($s = strrpos($original_launcher_contents, '$LOG_FILE'))) { $launcher_contents = substr($original_launcher_contents, 0, $s); $test_binary = pts_strings::first_in_string(trim(str_replace(array(' ', ' ', 'mpirun', 'mpiexec', './'), '', substr($launcher_contents, strrpos($launcher_contents, PHP_EOL) + 1)))); } if($test_binary) { if(is_executable($test_profile->get_test_executable_dir() . '/' . $test_binary)) { $test_binary = $test_profile->get_test_executable_dir() . '/' . $test_binary; } else if(($s = strpos($launcher_contents, PHP_EOL . 'cd '))) { $cd = (substr($launcher_contents, ($s + 4))); $cd = substr($cd, 0, strpos($cd, PHP_EOL)); if(is_executable($test_profile->get_test_executable_dir() . '/' . $cd . '/' . $test_binary)) { $test_binary = $test_profile->get_test_executable_dir() . '/' . $cd . '/' . $test_binary; } } } return $test_binary; } public static function analyze_binary_instruction_usage(&$binary) { // Based on data from https://github.com/dirtyepic/scripts/blob/master/analyze-x86 $instruction_checks = array( 'MMX' => array('emms', 'maskmovq', 'movq', 'movntq', 'packssdw', 'packsswb', 'packuswb', 'paddb', 'paddd', 'paddsb', 'paddsw', 'paddusb', 'paddusw', 'paddw', 'pand', 'pandn', 'pavgusb', 'pavgb', 'pavgw', 'pcmpeqb', 'pcmpeqd', 'pcmpeqw', 'pcmpgtb', 'pcmpgtd', 'pcmpgtw', 'pextrw', 'pinsrw', 'pmaddwd', 'pmaxsw', 'pmaxub', 'pminsw', 'pminub', 'pmovmskb', 'pmulhw', 'pmullw', 'pmulhuw', 'por', 'psadbw', 'pshufw', 'pslld', 'psllq', 'psllw', 'psrad', 'psraw', 'psrld', 'psrlq', 'psrlw', 'psubb', 'psubd', 'psubsb', 'psubsw', 'psubusb', 'psubusw', 'psubw', 'punpckhbw', 'punpckhdq', 'punpckhwd', 'punpcklbw', 'punpckldq', 'punpcklwd', 'pxor'), 'SSE' => array('addps', 'addss', 'andnps', 'andps', 'cmpeqps', 'cmpeqss', 'cmpleps', 'cmpless', 'cmpltps', 'cmpltss', 'cmpneqps', 'cmpneqss', 'cmpnleps', 'cmpnless', 'cmpnltps', 'cmpnltss', 'cmpordps', 'cmpordss', 'cmpps', 'cmpss', 'cmpunordps', 'cmpunordss', 'comiss', 'cvtpi2ps', 'cvtps2pi', 'cvtsi2ss', 'cvtss2si', 'cvttps2pi', 'cvttss2si', 'divps', 'divss', 'ldmxcsr', 'maxps', 'maxss', 'minps', 'minss', 'movaps', 'movhlps', 'movhps', 'movlhps', 'movlps', 'movmskps', 'movntps', 'movss', 'movups', 'mulps', 'mulss', 'orps', 'rcpps', 'rcpss', 'rsqrtps', 'rsqrtss', 'shufps', 'sqrtps', 'sqrtss', 'stmxcsr', 'subps', 'subss', 'ucomiss', 'unpckhps', 'unpcklps', 'xorps'), 'SSE2' => array('addpd', 'addsd', 'andnpd', 'andpd', 'clflush', 'cmpeqpd', 'cmpeqsd', 'cmplepd', 'cmplesd', 'cmpltpd', 'cmpltsd', 'cmpneqpd', 'cmpneqsd', 'cmpnlepd', 'cmpnlesd', 'cmpnltpd', 'cmpnltsd', 'cmpordpd', 'cmpordsd', 'cmppd', 'cmpunordpd', 'cmpunordsd', 'comisd', 'cvtdq2pd', 'cvtdq2ps', 'cvtpd2dq', 'cvtpd2pi', 'cvtpd2ps', 'cvtpi2pd', 'cvtps2dq', 'cvtps2pd', 'cvtsd2si', 'cvtsd2ss', 'cvtsi2sd', 'cvtss2sd', 'cvttpd2dq', 'cvttpd2pi', 'cvttps2dq', 'cvttsd2si', 'divpd', 'divsd', 'maskmovdqu', 'maxpd', 'maxsd', 'minpd', 'minsd', 'movapd', 'movdq2q', 'movdqa', 'movdqu', 'movhpd', 'movlpd', 'movmskpd', 'movntdq', 'movnti', 'movntpd', 'movq2dq', 'movupd', 'mulpd', 'mulsd', 'orpd', 'paddq', 'pmuludq', 'pshufd', 'pshufhw', 'pshuflw', 'pslldq', 'psrldq', 'psubq', 'punpckhqdq', 'punpcklqdq', 'shufpd', 'sqrtpd', 'sqrtsd', 'subpd', 'subsd', 'ucomisd', 'unpckhpd', 'unpcklpd', 'xorpd', 'movd'), 'SSE3' => array('addsubpd', 'addsubps', 'fisttp', 'haddpd', 'haddps', 'hsubpd', 'hsubps', 'lddqu', 'monitor', 'movddup', 'movshdup', 'movsldup', 'mwait'), 'SSSE3' => array('pabsb', 'pabsd', 'pabsw', 'palignr', 'phaddd', 'phaddsw', 'phaddw', 'phsubd', 'phsubsw', 'phsubw', 'pmaddubsw', 'pmulhrsw', 'pshufb', 'psignb', 'psignd', 'psignw'), 'SSE4_1' => array('blendpd', 'blendps', 'blendvpd', 'blendvps', 'dppd', 'dpps', 'extractps', 'insertps', 'movntdqa', 'mpsadbw', 'packusdw', 'pblendvb', 'pblendw', 'pcmpeqq', 'pextrb', 'pextrd', 'pextrq', 'phminposuw', 'pinsrb', 'pinsrd', 'pinsrq', 'pmaxsb', 'pmaxsd', 'pmaxud', 'pmaxuw', 'pminsb', 'pminsd', 'pminud', 'pminuw', 'pmovsxbd', 'pmovsxbq', 'pmovsxbw', 'pmovsxdq', 'pmovsxwd', 'pmovsxwq', 'pmovzxbd', 'pmovzxbq', 'pmovzxbw', 'pmovzxdq', 'pmovzxwd', 'pmovzxwq', 'pmuldq', 'pmulld', 'ptest', 'roundpd', 'roundps', 'roundsd', 'roundss'), 'SSE4_2' => array('crc32', 'pcmpestri', 'pcmpestrm', 'pcmpgtq', 'pcmpistri', 'pcmpistrm', 'popcnt'), 'SSE4A' => array('extrq', 'insertq', 'movntsd', 'movntss'), 'AVX' => array('pclmulhqhqdq', 'pclmulhqlqdq', 'pclmullqhqdq', 'pclmullqlqdq', 'pclmulqdq', 'vaddpd', 'vaddps', 'vaddsd', 'vaddss', 'vaddsubpd', 'vaddsubps', 'vaesdec', 'vaesdeclast', 'vaesenc', 'vaesenclast', 'vaesimc', 'vaeskeygenassist', 'vandnpd', 'vandnps', 'vandpd', 'vandps', 'vblendpd', 'vblendps', 'vblendvpd', 'vblendvps', 'vbroadcastf128', 'vbroadcastsd', 'vbroadcastss', 'vcmpeq_ospd', 'vcmpeq_osps', 'vcmpeq_ossd', 'vcmpeq_osss', 'vcmpeqpd', 'vcmpeqps', 'vcmpeqsd', 'vcmpeqss', 'vcmpeq_uqpd', 'vcmpeq_uqps', 'vcmpeq_uqsd', 'vcmpeq_uqss', 'vcmpeq_uspd', 'vcmpeq_usps', 'vcmpeq_ussd', 'vcmpeq_usss', 'vcmpfalse_oqpd', 'vcmpfalse_oqps', 'vcmpfalse_oqsd', 'vcmpfalse_oqss', 'vcmpfalse_ospd', 'vcmpfalse_osps', 'vcmpfalse_ossd', 'vcmpfalse_osss', 'vcmpfalsepd', 'vcmpfalseps', 'vcmpfalsesd', 'vcmpfalsess', 'vcmpge_oqpd', 'vcmpge_oqps', 'vcmpge_oqsd', 'vcmpge_oqss', 'vcmpge_ospd', 'vcmpge_osps', 'vcmpge_ossd', 'vcmpge_osss', 'vcmpgepd', 'vcmpgeps', 'vcmpgesd', 'vcmpgess', 'vcmpgt_oqpd', 'vcmpgt_oqps', 'vcmpgt_oqsd', 'vcmpgt_oqss', 'vcmpgt_ospd', 'vcmpgt_osps', 'vcmpgt_ossd', 'vcmpgt_osss', 'vcmpgtpd', 'vcmpgtps', 'vcmpgtsd', 'vcmpgtss', 'vcmple_oqpd', 'vcmple_oqps', 'vcmple_oqsd', 'vcmple_oqss', 'vcmple_ospd', 'vcmple_osps', 'vcmple_ossd', 'vcmple_osss', 'vcmplepd', 'vcmpleps', 'vcmplesd', 'vcmpless', 'vcmplt_oqpd', 'vcmplt_oqps', 'vcmplt_oqsd', 'vcmplt_oqss', 'vcmplt_ospd', 'vcmplt_osps', 'vcmplt_ossd', 'vcmplt_osss', 'vcmpltpd', 'vcmpltps', 'vcmpltsd', 'vcmpltss', 'vcmpneq_oqpd', 'vcmpneq_oqps', 'vcmpneq_oqsd', 'vcmpneq_oqss', 'vcmpneq_ospd', 'vcmpneq_osps', 'vcmpneq_ossd', 'vcmpneq_osss', 'vcmpneqpd', 'vcmpneqps', 'vcmpneqsd', 'vcmpneqss', 'vcmpneq_uqpd', 'vcmpneq_uqps', 'vcmpneq_uqsd', 'vcmpneq_uqss', 'vcmpneq_uspd', 'vcmpneq_usps', 'vcmpneq_ussd', 'vcmpneq_usss', 'vcmpngepd', 'vcmpngeps', 'vcmpngesd', 'vcmpngess', 'vcmpnge_uqpd', 'vcmpnge_uqps', 'vcmpnge_uqsd', 'vcmpnge_uqss', 'vcmpnge_uspd', 'vcmpnge_usps', 'vcmpnge_ussd', 'vcmpnge_usss', 'vcmpngtpd', 'vcmpngtps', 'vcmpngtsd', 'vcmpngtss', 'vcmpngt_uqpd', 'vcmpngt_uqps', 'vcmpngt_uqsd', 'vcmpngt_uqss', 'vcmpngt_uspd', 'vcmpngt_usps', 'vcmpngt_ussd', 'vcmpngt_usss', 'vcmpnlepd', 'vcmpnleps', 'vcmpnlesd', 'vcmpnless', 'vcmpnle_uqpd', 'vcmpnle_uqps', 'vcmpnle_uqsd', 'vcmpnle_uqss', 'vcmpnle_uspd', 'vcmpnle_usps', 'vcmpnle_ussd', 'vcmpnle_usss', 'vcmpnltpd', 'vcmpnltps', 'vcmpnltsd', 'vcmpnltss', 'vcmpnlt_uqpd', 'vcmpnlt_uqps', 'vcmpnlt_uqsd', 'vcmpnlt_uqss', 'vcmpnlt_uspd', 'vcmpnlt_usps', 'vcmpnlt_ussd', 'vcmpnlt_usss', 'vcmpordpd', 'vcmpordps', 'vcmpord_qpd', 'vcmpord_qps', 'vcmpord_qsd', 'vcmpord_qss', 'vcmpordsd', 'vcmpord_spd', 'vcmpord_sps', 'vcmpordss', 'vcmpord_ssd', 'vcmpord_sss', 'vcmppd', 'vcmpps', 'vcmpsd', 'vcmpss', 'vcmptruepd', 'vcmptrueps', 'vcmptruesd', 'vcmptruess', 'vcmptrue_uqpd', 'vcmptrue_uqps', 'vcmptrue_uqsd', 'vcmptrue_uqss', 'vcmptrue_uspd', 'vcmptrue_usps', 'vcmptrue_ussd', 'vcmptrue_usss', 'vcmpunordpd', 'vcmpunordps', 'vcmpunord_qpd', 'vcmpunord_qps', 'vcmpunord_qsd', 'vcmpunord_qss', 'vcmpunordsd', 'vcmpunord_spd', 'vcmpunord_sps', 'vcmpunordss', 'vcmpunord_ssd', 'vcmpunord_sss', 'vcomisd', 'vcomiss', 'vcvtdq2pd', 'vcvtdq2ps', 'vcvtpd2dq', 'vcvtpd2ps', 'vcvtps2dq', 'vcvtps2pd', 'vcvtsd2si', 'vcvtsd2ss', 'vcvtsi2sd', 'vcvtsi2ss', 'vcvtss2sd', 'vcvtss2si', 'vcvttpd2dq', 'vcvttps2dq', 'vcvttsd2si', 'vcvttss2si', 'vdivpd', 'vdivps', 'vdivsd', 'vdivss', 'vdppd', 'vdpps', 'vextractf128', 'vextractps', 'vhaddpd', 'vhaddps', 'vhsubpd', 'vhsubps', 'vinsertf128', 'vinsertps', 'vlddqu', 'vldmxcsr', 'vldqqu', 'vmaskmovdqu', 'vmaskmovpd', 'vmaskmovps', 'vmaxpd', 'vmaxps', 'vmaxsd', 'vmaxss', 'vminpd', 'vminps', 'vminsd', 'vminss', 'vmovapd', 'vmovaps', 'vmovd', 'vmovddup', 'vmovdqa', 'vmovdqu', 'vmovhlps', 'vmovhpd', 'vmovhps', 'vmovlhps', 'vmovlpd', 'vmovlps', 'vmovmskpd', 'vmovmskps', 'vmovntdq', 'vmovntdqa', 'vmovntpd', 'vmovntps', 'vmovntqq', 'vmovq', 'vmovqqa', 'vmovqqu', 'vmovsd', 'vmovshdup', 'vmovsldup', 'vmovss', 'vmovupd', 'vmovups', 'vmpsadbw', 'vmulpd', 'vmulps', 'vmulsd', 'vmulss', 'vorpd', 'vorps', 'vpabsb', 'vpabsd', 'vpabsw', 'vpackssdw', 'vpacksswb', 'vpackusdw', 'vpackuswb', 'vpaddb', 'vpaddd', 'vpaddq', 'vpaddsb', 'vpaddsw', 'vpaddusb', 'vpaddusw', 'vpaddw', 'vpalignr', 'vpand', 'vpandn', 'vpavgb', 'vpavgw', 'vpblendvb', 'vpblendw', 'vpclmulhqhqdq', 'vpclmulhqlqdq', 'vpclmullqhqdq', 'vpclmullqlqdq', 'vpclmulqdq', 'vpcmpeqb', 'vpcmpeqd', 'vpcmpeqq', 'vpcmpeqw', 'vpcmpestri', 'vpcmpestrm', 'vpcmpgtb', 'vpcmpgtd', 'vpcmpgtq', 'vpcmpgtw', 'vpcmpistri', 'vpcmpistrm', 'vperm2f128', 'vpermilpd', 'vpermilps', 'vpextrb', 'vpextrd', 'vpextrq', 'vpextrw', 'vphaddd', 'vphaddsw', 'vphaddw', 'vphminposuw', 'vphsubd', 'vphsubsw', 'vphsubw', 'vpinsrb', 'vpinsrd', 'vpinsrq', 'vpinsrw', 'vpmaddubsw', 'vpmaddwd', 'vpmaxsb', 'vpmaxsd', 'vpmaxsw', 'vpmaxub', 'vpmaxud', 'vpmaxuw', 'vpminsb', 'vpminsd', 'vpminsw', 'vpminub', 'vpminud', 'vpminuw', 'vpmovmskb', 'vpmovsxbd', 'vpmovsxbq', 'vpmovsxbw', 'vpmovsxdq', 'vpmovsxwd', 'vpmovsxwq', 'vpmovzxbd', 'vpmovzxbq', 'vpmovzxbw', 'vpmovzxdq', 'vpmovzxwd', 'vpmovzxwq', 'vpmuldq', 'vpmulhrsw', 'vpmulhuw', 'vpmulhw', 'vpmulld', 'vpmullw', 'vpmuludq', 'vpor', 'vpsadbw', 'vpshufb', 'vpshufd', 'vpshufhw', 'vpshuflw', 'vpsignb', 'vpsignd', 'vpsignw', 'vpslld', 'vpslldq', 'vpsllq', 'vpsllw', 'vpsrad', 'vpsraw', 'vpsrld', 'vpsrldq', 'vpsrlq', 'vpsrlw', 'vpsubb', 'vpsubd', 'vpsubq', 'vpsubsb', 'vpsubsw', 'vpsubusb', 'vpsubusw', 'vpsubw', 'vptest', 'vpunpckhbw', 'vpunpckhdq', 'vpunpckhqdq', 'vpunpckhwd', 'vpunpcklbw', 'vpunpckldq', 'vpunpcklqdq', 'vpunpcklwd', 'vpxor', 'vrcpps', 'vrcpss', 'vroundpd', 'vroundps', 'vroundsd', 'vroundss', 'vrsqrtps', 'vrsqrtss', 'vshufpd', 'vshufps', 'vsqrtpd', 'vsqrtps', 'vsqrtsd', 'vsqrtss', 'vstmxcsr', 'vsubpd', 'vsubps', 'vsubsd', 'vsubss', 'vtestpd', 'vtestps', 'vucomisd', 'vucomiss', 'vunpckhpd', 'vunpckhps', 'vunpcklpd', 'vunpcklps', 'vxorpd', 'vxorps', 'vzeroall', 'vzeroupper'), 'FMA' => array('vfmadd123pd', 'vfmadd123ps', 'vfmadd123sd', 'vfmadd123ss', 'vfmadd132pd', 'vfmadd132ps', 'vfmadd132sd', 'vfmadd132ss', 'vfmadd213pd', 'vfmadd213ps', 'vfmadd213sd', 'vfmadd213ss', 'vfmadd231pd', 'vfmadd231ps', 'vfmadd231sd', 'vfmadd231ss', 'vfmadd312pd', 'vfmadd312ps', 'vfmadd312sd', 'vfmadd312ss', 'vfmadd321pd', 'vfmadd321ps', 'vfmadd321sd', 'vfmadd321ss', 'vfmaddsub123pd', 'vfmaddsub123ps', 'vfmaddsub132pd', 'vfmaddsub132ps', 'vfmaddsub213pd', 'vfmaddsub213ps', 'vfmaddsub231pd', 'vfmaddsub231ps', 'vfmaddsub312pd', 'vfmaddsub312ps', 'vfmaddsub321pd', 'vfmaddsub321ps', 'vfmsub123pd', 'vfmsub123ps', 'vfmsub123sd', 'vfmsub123ss', 'vfmsub132pd', 'vfmsub132ps', 'vfmsub132sd', 'vfmsub132ss', 'vfmsub213pd', 'vfmsub213ps', 'vfmsub213sd', 'vfmsub213ss', 'vfmsub231pd', 'vfmsub231ps', 'vfmsub231sd', 'vfmsub231ss', 'vfmsub312pd', 'vfmsub312ps', 'vfmsub312sd', 'vfmsub312ss', 'vfmsub321pd', 'vfmsub321ps', 'vfmsub321sd', 'vfmsub321ss', 'vfmsubadd123pd', 'vfmsubadd123ps', 'vfmsubadd132pd', 'vfmsubadd132ps', 'vfmsubadd213pd', 'vfmsubadd213ps', 'vfmsubadd231pd', 'vfmsubadd231ps', 'vfmsubadd312pd', 'vfmsubadd312ps', 'vfmsubadd321pd', 'vfmsubadd321ps', 'vfnmadd123pd', 'vfnmadd123ps', 'vfnmadd123sd', 'vfnmadd123ss', 'vfnmadd132pd', 'vfnmadd132ps', 'vfnmadd132sd', 'vfnmadd132ss', 'vfnmadd213pd', 'vfnmadd213ps', 'vfnmadd213sd', 'vfnmadd213ss', 'vfnmadd231pd', 'vfnmadd231ps', 'vfnmadd231sd', 'vfnmadd231ss', 'vfnmadd312pd', 'vfnmadd312ps', 'vfnmadd312sd', 'vfnmadd312ss', 'vfnmadd321pd', 'vfnmadd321ps', 'vfnmadd321sd', 'vfnmadd321ss', 'vfnmsub123pd', 'vfnmsub123ps', 'vfnmsub123sd', 'vfnmsub123ss', 'vfnmsub132pd', 'vfnmsub132ps', 'vfnmsub132sd', 'vfnmsub132ss', 'vfnmsub213pd', 'vfnmsub213ps', 'vfnmsub213sd', 'vfnmsub213ss', 'vfnmsub231pd', 'vfnmsub231ps', 'vfnmsub231sd', 'vfnmsub231ss', 'vfnmsub312pd', 'vfnmsub312ps', 'vfnmsub312sd', 'vfnmsub312ss', 'vfnmsub321pd', 'vfnmsub321ps', 'vfnmsub321sd', 'vfnmsub321ss'), 'FMA4' => array('vfmaddpd', 'vfmaddps', 'vfmaddsd', 'vfmaddss', 'vfmaddsubpd', 'vfmaddsubps', 'vfmsubaddpd', 'vfmsubaddps', 'vfmsubpd', 'vfmsubps', 'vfmsubsd', 'vfmsubss', 'vfnmaddpd', 'vfnmaddps', 'vfnmaddsd', 'vfnmaddss', 'vfnmsubpd', 'vfnmsubps', 'vfnmsubsd', 'vfnmsubss', 'vfrczpd', 'vfrczps', 'vfrczsd', 'vfrczss', 'vpcmov', 'vpcomb', 'vpcomd', 'vpcomq', 'vpcomub', 'vpcomud', 'vpcomuq', 'vpcomuw', 'vpcomw', 'vphaddbd', 'vphaddbq', 'vphaddbw', 'vphadddq', 'vphaddubd', 'vphaddubq', 'vphaddubw', 'vphaddudq', 'vphadduwd', 'vphadduwq', 'vphaddwd', 'vphaddwq', 'vphsubbw', 'vphsubdq', 'vphsubwd', 'vpmacsdd', 'vpmacsdqh', 'vpmacsdql', 'vpmacssdd', 'vpmacssdqh', 'vpmacssdql', 'vpmacsswd', 'vpmacssww', 'vpmacswd', 'vpmacsww', 'vpmadcsswd', 'vpmadcswd', 'vpperm', 'vprotb', 'vprotd', 'vprotq', 'vprotw', 'vpshab', 'vpshad', 'vpshaq', 'vpshaw', 'vpshlb', 'vpshld', 'vpshlq', 'vpshlw'), ); foreach(array_keys($instruction_checks) as $set) { $instruction_usage[$set] = 0; } $instruction_usage['OTHER'] = 0; foreach(explode(PHP_EOL , shell_exec('objdump -d ' . $binary . ' | cut -f3 | cut -d\' \' -f1')) as $instruction) { $matched_instruction = false; foreach($instruction_checks as $set => $instructions) { if(in_array(trim($instruction), $instructions)) { $instruction_usage[$set] += 1; $matched_instruction = true; break; } } if($matched_instruction == false) { $instruction_usage['OTHER'] += 1; } } foreach($instruction_usage as $instruction => $usage) { if($usage < 2) { unset($instruction_usage[$instruction]); } } return $instruction_usage; } public static function analyze_apitrace_trace_glpop($apitrace_file) { $tracedump = trim(shell_exec('apitrace dump --call-nos=no ' . $apitrace_file)); $gl_usage = array(); while($tracedump && ($break = strpos($tracedump, PHP_EOL)) != false) { $line = substr($tracedump, 0, $break); $tracedump = substr($tracedump, $break + 1); $line = substr($line, 0, strpos($line, '(')); if(strtolower(substr($line, 0, 2)) == 'gl') { if(isset($gl_usage[$line])) { $gl_usage[$line]++; } else if(ctype_alnum($line)) { $gl_usage[$line] = 1; } } } arsort($gl_usage); $gl_usage = array_keys($gl_usage); return $gl_usage; } } ?> phoronix-test-suite/pts-core/commands/batch_run.php0000644000175000017500000000264511747265231022650 0ustar michaelmichael. */ class batch_run implements pts_option_interface { const doc_section = 'Batch Testing'; const doc_description = 'This option and its arguments are equivalent to the run option, but the process will be run in the Phoronix Test Suite batch mode.'; public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_types', 'identifier_to_object'), null) ); } public static function run($r) { pts_test_run_manager::standard_run($r, pts_c::batch_mode); } public static function invalid_command($passed_args = null) { pts_tests::invalid_command_helper($passed_args); } } ?> phoronix-test-suite/pts-core/commands/system_info.php0000644000175000017500000000244311733757703023243 0ustar michaelmichael. */ class system_info implements pts_option_interface { const doc_section = 'System'; const doc_description = 'Display the installed system hardware and software information as detected by the Phoronix Test Suite Phodevi Library.'; public static function run($r) { pts_client::$display->generic_heading('System Information'); echo 'Hardware:' . PHP_EOL . phodevi::system_hardware(true) . PHP_EOL . PHP_EOL; echo 'Software:' . PHP_EOL . phodevi::system_software(true) . PHP_EOL . PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/list_test_usage.php0000644000175000017500000000425511741706052024073 0ustar michaelmichael. */ class list_test_usage implements pts_option_interface { const doc_section = 'Information'; const doc_description = 'This option will list various details about installed tests and their usage.'; public static function run($r) { $installed_tests = pts_tests::installed_tests(); pts_client::$display->generic_heading(count($installed_tests) . ' Tests Installed'); if(count($installed_tests) > 0) { echo sprintf('%-18ls %-8ls %-13ls %-11ls %-13ls %-10ls', 'TEST', 'VERSION', 'INSTALL DATE', 'LAST RUN', 'AVG RUN-TIME', 'TIMES RUN') . PHP_EOL; foreach($installed_tests as $identifier) { $test_profile = new pts_test_profile($identifier); if($test_profile && $test_profile->test_installation && $test_profile->test_installation->get_installed_version() != null) { $avg_time = $test_profile->test_installation->get_average_run_time(); $avg_time = !empty($avg_time) ? pts_strings::format_time($avg_time, 'SECONDS', false) : 'N/A'; $last_run = $test_profile->test_installation->get_last_run_date(); $last_run = $last_run == '0000-00-00' ? 'NEVER' : $last_run; echo sprintf('%-18ls - %-8ls %-13ls %-11ls %-13ls %-10ls', $identifier, $test_profile->test_installation->get_installed_version(), $test_profile->test_installation->get_install_date(), $last_run, $avg_time, $test_profile->test_installation->get_run_count()) . PHP_EOL; } } } } } ?> phoronix-test-suite/pts-core/commands/module_info.php0000644000175000017500000000426711607051665023204 0ustar michaelmichael. */ class module_info implements pts_option_interface { const doc_section = 'Modules'; const doc_description = 'This option will show detailed information on a Phoronix Test Suite module such as the version, developer, and a description of its purpose.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_module', 'is_module'), null) ); } public static function run($args) { $module = $args[0]; pts_module_manager::load_module($module); pts_client::$display->generic_heading(pts_module_manager::module_call($module, 'module_name') . ' Module'); if(in_array($args[0], pts_module_manager::attached_modules())) { echo '** This module is currently loaded. **' . PHP_EOL; } echo 'Version: ' . pts_module_manager::module_call($module, 'module_version') . PHP_EOL; echo 'Author: ' . pts_module_manager::module_call($module, 'module_author') . PHP_EOL; echo 'Description: ' . pts_module_manager::module_call($module, 'module_description') . PHP_EOL; echo PHP_EOL . pts_module_manager::module_call($module, 'module_info') . PHP_EOL; $all_options = pts_module_manager::module_call($module, 'user_commands'); if(count($all_options) > 0) { echo 'Module User Commands:' . PHP_EOL; foreach(array_keys($all_options) as $option) { echo '- ' . $module . '.' . str_replace('_', '-', $option) . PHP_EOL; } echo PHP_EOL; } } } ?> phoronix-test-suite/pts-core/commands/list_modules.php0000644000175000017500000000277611607050622023402 0ustar michaelmichael. */ class list_modules implements pts_option_interface { const doc_section = 'Modules'; const doc_description = 'This option will list all of the available Phoronix Test Suite modules on this system.'; public static function run($r) { pts_client::$display->generic_heading(count(pts_module_manager::available_modules()) . ' Modules'); foreach(pts_module_manager::available_modules() as $module) { pts_module_manager::load_module($module); echo sprintf('%-22ls - %-32ls [%s]' . PHP_EOL, $module, pts_module_manager::module_call($module, 'module_name') . ' v' . pts_module_manager::module_call($module, 'module_version'), pts_module_manager::module_call($module, 'module_author')); } echo PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/result_file_to_csv.php0000644000175000017500000000315411713747223024570 0ustar michaelmichael. */ class result_file_to_csv implements pts_option_interface { const doc_section = 'Result Management'; const doc_description = 'This option will read a saved test results file and output the system hardware and software information along with the results to a CSV output. The CSV (Comma Separated Values) output can then be loaded into a spreadsheet for easy viewing.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function run($r) { $result_file = new pts_result_file($r[0]); $result_output = pts_result_file_output::result_file_to_csv($result_file); // To save the result: $file = pts_client::user_home_directory() . $r[0] . '.csv'; file_put_contents($file, $result_output); echo $result_output; } } ?> phoronix-test-suite/pts-core/commands/help.php0000644000175000017500000000317111670017446021624 0ustar michaelmichael. */ class help implements pts_option_interface { const doc_section = 'Other'; const doc_description = 'This option will display the list of available Phoronix Test Suite commands.'; public static function run($r) { echo PHP_EOL . pts_title(true) . PHP_EOL . PHP_EOL; echo pts_documentation::basic_description() . PHP_EOL . PHP_EOL . 'View the included PDF / HTML documentation or visit http://www.phoronix-test-suite.com/ for full details.' . PHP_EOL; $options = pts_documentation::client_commands_array(); foreach($options as $section => &$contents) { if(empty($contents)) { continue; } echo PHP_EOL . strtoupper($section) . PHP_EOL . PHP_EOL; sort($contents); foreach($contents as &$option) { echo ' ' . trim($option[0] . ' ' . implode(' ', $option[1])) . PHP_EOL; } } echo PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/run_test.php0000644000175000017500000000264211670224306022534 0ustar michaelmichael. */ class run_test implements pts_option_interface { const doc_section = 'Testing'; const doc_use_alias = 'run'; const doc_description = 'This option will run the selected test(s).'; public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_types', 'identifier_to_object'), null) ); } public static function command_aliases() { return array('run'); } public static function invalid_command($passed_args = null) { pts_tests::invalid_command_helper($passed_args); } public static function run($to_run) { pts_test_run_manager::standard_run($to_run); } } ?> phoronix-test-suite/pts-core/commands/upload_test_suite.php0000644000175000017500000000701711667675413024445 0ustar michaelmichael. */ class upload_test_suite implements pts_option_interface { const doc_section = 'OpenBenchmarking.org'; const doc_description = 'This option can be used for uploading a test suite to your account on OpenBenchmarking.org. By uploading your test suite to OpenBenchmarking.org, others are then able to browse and access this test suite for easy distribution.'; public static function run($r) { if(pts_openbenchmarking_client::user_name() == false) { echo PHP_EOL . 'You must first be logged into an OpenBenchmarking.org account.' . PHP_EOL; echo PHP_EOL . 'Create An Account: http://openbenchmarking.org/'; echo PHP_EOL . 'Log-In Command: phoronix-test-suite openbenchmarking-setup' . PHP_EOL . PHP_EOL; return false; } if(($test_suite = pts_types::identifier_to_object($r[0])) != false) { pts_client::$display->generic_heading($r[0]); if(pts_validation::validate_test_suite($test_suite)) { $zip_file = PTS_OPENBENCHMARKING_SCRATCH_PATH . $test_suite->get_identifier(false) . '-' . $test_suite->get_version() . '.zip'; $zip_created = pts_compression::zip_archive_create($zip_file, $test_suite->xml_parser->getFileLocation()); if($zip_created == false) { echo PHP_EOL . 'Failed to create zip file.' . PHP_EOL; return false; } $zip = new ZipArchive(); $zip->open($zip_file); $zip->renameName(basename($test_suite->xml_parser->getFileLocation()), 'suite-definition.xml'); $zip->close(); $commit_description = pts_user_io::prompt_user_input('Enter a test commit description', false); echo PHP_EOL; $server_response = pts_openbenchmarking::make_openbenchmarking_request('upload_test_suite', array( 'ts_identifier' => $test_suite->get_identifier_base_name(), 'ts_sha1' => sha1_file($zip_file), 'ts_zip' => base64_encode(file_get_contents($zip_file)), 'ts_zip_name' => basename($zip_file), 'commit_description' => $commit_description )); echo PHP_EOL; $json = json_decode($server_response, true); if(isset($json['openbenchmarking']['upload']['error']) && !empty($json['openbenchmarking']['upload']['error'])) { echo 'ERROR: ' . $json['openbenchmarking']['upload']['error'] . PHP_EOL; } if(isset($json['openbenchmarking']['upload']['id']) && !empty($json['openbenchmarking']['upload']['id'])) { echo 'Command: phoronix-test-suite benchmark ' . $json['openbenchmarking']['upload']['id'] . PHP_EOL; } if(isset($json['openbenchmarking']['upload']['url']) && !empty($json['openbenchmarking']['upload']['url'])) { pts_openbenchmarking_client::refresh_repository_lists(null, true); echo 'URL: ' . $json['openbenchmarking']['upload']['url'] . PHP_EOL; } echo PHP_EOL; unlink($zip_file); } } } } ?> phoronix-test-suite/pts-core/commands/install_test.php0000644000175000017500000000405511670224411023373 0ustar michaelmichael. */ class install_test implements pts_option_interface { const doc_section = 'Test Installation'; const doc_use_alias = 'install'; const doc_description = 'This option will install the selected test(s) inside the testing environment directory). The install process from downloading of the test files to the installation is fully automated. The install option needs to be supplied with the test name or suite as an argument. Optionally, a OpenBenchmarking.org ID or the name of a saved results file can be supplied as well and the test(s) to install will automatically be extracted from that information. If the test is already installed and was run by the latest version of the installation process, no action will be taken. Multiple arguments can be supplied to install additional tests at the same time.'; public static function command_aliases() { return array('install'); } public static function invalid_command($passed_args = null) { pts_tests::invalid_command_helper($passed_args); } public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_types', 'identifier_to_object'), null) ); } public static function run($items_to_install) { pts_test_installer::standard_install($items_to_install); } } ?> phoronix-test-suite/pts-core/commands/validate_result_file.php0000644000175000017500000000304211564533734025064 0ustar michaelmichael. */ class validate_result_file implements pts_option_interface { const doc_section = 'Asset Creation'; const doc_description = 'This option can be used for validating a Phoronix Test Suite result file as being compliant against the OpenBenchmarking.org specification.'; public static function run($r) { if(pts_result_file::is_test_result_file($r[0])) { $result_file = new pts_result_file($r[0]); pts_client::$display->generic_heading($r[0]); $valid = $result_file->xml_parser->validate(); if($valid == false) { echo PHP_EOL . 'Errors occurred parsing the main XML.' . PHP_EOL; pts_validation::process_libxml_errors(); return false; } else { echo PHP_EOL . 'The result file is Valid.' . PHP_EOL; } } } } ?> phoronix-test-suite/pts-core/commands/user_config_set.php0000644000175000017500000000400411564533734024053 0ustar michaelmichael. */ class user_config_set implements pts_option_interface { const doc_section = 'Other'; const doc_description = 'This option can be used for setting an XML value in the Phoronix Test Suite user configuration file.'; public static function run($r) { if(count($r) == 0) { echo PHP_EOL . 'You must specify the tag to override along with the value.' . PHP_EOL; echo 'Example: phoronix-test-suite user-config-set CacheDirectory=~/cache/' . PHP_EOL . PHP_EOL; return false; } $new_options = array(); foreach($r as $user_option) { $user_option_r = explode('=', $user_option); if(count($user_option_r) > 1) { $user_value = substr($user_option, strlen($user_option_r[0]) + 1); if(substr($user_value, 0, 1) == '"') { $user_value = substr($user_value, 1); } if(substr($user_value, -1) == '"') { $user_value = substr($user_value, 0, -1); } if(!in_array(basename($user_option_r[0]), array('AgreementCheckSum', 'GSID'))) // List any XML tags to ignore in this array { $new_options[$user_option_r[0]] = $user_value; } } } pts_config::user_config_generate($new_options); echo PHP_EOL . 'New user configuration file written.' . PHP_EOL . PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/benchmark.php0000644000175000017500000000327111670224374022627 0ustar michaelmichael. */ class benchmark implements pts_option_interface { const doc_section = 'Testing'; const doc_description = 'This option will install the selected test(s) (if needed) and will proceed to run the test(s). This option is equivalent to running phoronix-test-suite with the install option followed by the run option. Multiple arguments can be supplied to run additional tests at the same time and save the results into one file.'; public static function command_aliases() { return array('test'); } public static function invalid_command($passed_args = null) { pts_tests::invalid_command_helper($passed_args); } public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_types', 'identifier_to_object'), null) ); } public static function run($r) { pts_test_installer::standard_install($r); pts_test_run_manager::standard_run($r); } } ?> phoronix-test-suite/pts-core/commands/user_config_reset.php0000644000175000017500000000243011564533734024403 0ustar michaelmichael. */ class user_config_reset implements pts_option_interface { const doc_section = 'Other'; const doc_description = 'This option can be used for resetting the Phoronix Test Suite user configuration file to its default state.'; public static function run($r) { if(is_file(PTS_USER_PATH . 'user-config.xml')) { copy(PTS_USER_PATH . 'user-config.xml', PTS_USER_PATH . 'user-config-old.xml'); unlink(PTS_USER_PATH . 'user-config.xml'); } pts_config::user_config_generate(); } } ?> phoronix-test-suite/pts-core/commands/test_module.php0000644000175000017500000000340011564533734023220 0ustar michaelmichael. */ class test_module implements pts_option_interface { const doc_section = 'Modules'; const doc_description = 'This option can be used for debugging a Phoronix Test Suite module.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_module', 'is_module'), null) ); } public static function run($r) { $module = strtolower($r[0]); pts_module_manager::attach_module($module); $processes = array('__startup', '__pre_option_process', '__pre_install_process', '__pre_test_download', '__interim_test_download', '__post_test_download', '__pre_test_install', '__post_test_install', '__post_install_process', '__pre_run_process', '__pre_test_run', '__interim_test_run', '__post_test_run', '__post_run_process', '__post_option_process', '__shutdown'); foreach($processes as $process) { echo 'Calling: ' . $process . '()' . PHP_EOL; pts_module_manager::module_process($process); sleep(1); } echo PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/system_sensors.php0000644000175000017500000000301411564533734023775 0ustar michaelmichael. */ class system_sensors implements pts_option_interface { const doc_section = 'System'; const doc_description = 'Display the installed system hardware and software sensors in real-time as detected by the Phoronix Test Suite Phodevi Library.'; public static function run($r) { pts_client::$display->generic_heading('Supported Sensors'); foreach(phodevi::supported_sensors() as $sensor) { echo phodevi::sensor_name($sensor) . ': ' . phodevi::read_sensor($sensor) . ' ' . phodevi::read_sensor_unit($sensor) . PHP_EOL; } pts_client::$display->generic_heading('Unsupported Sensors'); foreach(phodevi::unsupported_sensors() as $sensor) { echo '- ' . phodevi::sensor_name($sensor) . PHP_EOL; } echo PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/run_tests_in_suite.php0000644000175000017500000000256011564533734024627 0ustar michaelmichael. */ class run_tests_in_suite implements pts_option_interface { const doc_section = 'Testing'; const doc_description = 'This option can be used if you wish to run all of the tests found in a supplied suite, but you wish to re-configure each of the test options rather than using the defaults supplied by the suite.'; public static function run($r) { $to_run = array(); foreach(pts_types::identifiers_to_test_profile_objects($r, false, true) as $test_profile) { pts_arrays::unique_push($to_run, $test_profile); } pts_test_run_manager::standard_run($to_run); } } ?> phoronix-test-suite/pts-core/commands/result_file_to_suite.php0000644000175000017500000000477711564533734025146 0ustar michaelmichael. */ class result_file_to_suite implements pts_option_interface { const doc_section = 'Asset Creation'; const doc_description = 'This option will guide the user through the process of generating their own test suite, which they can then run, that is based upon an existing test results file.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function run($r) { $result_file = false; if(count($r) != 0) { $result_file = $r[0]; } $suite_name = pts_user_io::prompt_user_input('Enter name of suite'); $suite_test_type = pts_user_io::prompt_text_menu('Select test type', pts_types::subsystem_targets()); $suite_maintainer = pts_user_io::prompt_user_input('Enter suite maintainer name'); $suite_description = pts_user_io::prompt_user_input('Enter suite description'); $suite_writer = new pts_test_suite_writer(); $suite_writer->add_suite_information($suite_name, '1.0.0', $suite_maintainer, $suite_test_type, $suite_description); // Read results file $result_file = new pts_result_file($result_file); foreach($result_file->get_result_objects() as $result_object) { $suite_writer->add_to_suite_from_result_object($result_object); } // Finish it off $suite_identifier = pts_test_run_manager::clean_save_name($suite_name); mkdir(PTS_TEST_SUITE_PATH . 'local/' . $suite_identifier); $save_to = PTS_TEST_SUITE_PATH . 'local/' . $suite_identifier . '/suite-definition.xml'; if($suite_writer->save_xml($save_to) != false) { echo PHP_EOL . PHP_EOL . 'Saved To: ' . $save_to . PHP_EOL . 'To run this suite, type: phoronix-test-suite benchmark ' . $suite_identifier . PHP_EOL . PHP_EOL; } } } ?> phoronix-test-suite/pts-core/commands/download_test_files.php0000644000175000017500000000314711564533733024733 0ustar michaelmichael. */ class download_test_files implements pts_option_interface { const doc_section = 'Asset Creation'; const doc_description = 'This will download the selected test file(s) to the Phoronix Test Suite download cache but will not install the tests.'; public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_types', 'is_test_or_suite'), null) ); } public static function run($r) { $test_profiles = pts_types::identifiers_to_test_profile_objects($r, true, true); if(count($test_profiles) > 0) { echo PHP_EOL . 'Downloading Test Files For: ' . implode(' ', $test_profiles); pts_test_installer::only_download_test_files($test_profiles, pts_client::read_env('DOWNLOAD_CACHE_LOCATION')); } else { echo PHP_EOL . 'Nothing found to download.' . PHP_EOL; } } } ?> phoronix-test-suite/pts-core/commands/default_run.php0000644000175000017500000000332011564533733023204 0ustar michaelmichael. */ class default_run implements pts_option_interface { const doc_section = 'Batch Testing'; const doc_description = 'This option will run the selected test(s). The name of the test or suite must be supplied or the OpenBenchmarking.org ID or saved local file name. Multiple arguments can be supplied to run additional tests at the same time and save the results in a suite-like fashion. Unlike the normal run option, the default-run will not prompt the user to select from the available test options but will instead use the default options as automatically set by pts-core or the test profile. Use batch-run to automatically test all of the available options.'; public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_types', 'identifier_to_object'), null) ); } public static function run($r) { pts_test_run_manager::standard_run($r, pts_c::defaults_mode); } } ?> phoronix-test-suite/pts-core/commands/debug_run.php0000644000175000017500000000266511564533733022661 0ustar michaelmichael. */ class debug_run implements pts_option_interface { const doc_section = 'Asset Creation'; const doc_description = 'This option is intended for use by test profile writers and is identical to the run option but will yield more information during the run process that can be used to debug issues with a test profile or to verify the test profile is functioning correctly.'; public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_types', 'identifier_to_object'), null) ); } public static function run($r) { pts_test_run_manager::standard_run($r, pts_c::debug_mode); } } ?> phoronix-test-suite/pts-core/commands/debug_install.php0000644000175000017500000000272711564533733023522 0ustar michaelmichael. */ class debug_install implements pts_option_interface { const doc_section = 'Asset Creation'; const doc_description = "This option is intended for use by test profile writers and is identical to the install option but will yield more information during the run process that can be used to debug issues with a test profile installer or to verify the test profile is functioning correctly."; public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_types', 'identifier_to_object'), null) ); } public static function run($r) { pts_test_installer::standard_install($r, pts_c::debug_mode | pts_c::force_install); } } ?> phoronix-test-suite/pts-core/commands/validate_test_profile.php0000644000175000017500000000247311622555532025250 0ustar michaelmichael. */ class validate_test_profile implements pts_option_interface { const doc_section = 'Asset Creation'; const doc_description = 'This option can be used for validating a Phoronix Test Suite test profile as being compliant against the OpenBenchmarking.org specification.'; public static function run($r) { foreach(pts_types::identifiers_to_test_profile_objects($r, true, true) as $test_profile) { pts_client::$display->generic_heading($test_profile); pts_validation::validate_test_profile($test_profile); } } } ?> phoronix-test-suite/pts-core/commands/validate_test_suite.php0000644000175000017500000000242611622554001024725 0ustar michaelmichael. */ class validate_test_suite implements pts_option_interface { const doc_section = 'Asset Creation'; const doc_description = 'This option can be used for validating a Phoronix Test Suite test suite as being compliant against the OpenBenchmarking.org specification.'; public static function run($r) { if(($test_suite = pts_types::identifier_to_object($r[0])) != false) { pts_client::$display->generic_heading($r[0]); pts_validation::validate_test_suite($test_suite); } } } ?> phoronix-test-suite/pts-core/commands/result_file_to_pdf.php0000644000175000017500000000723211743145160024542 0ustar michaelmichael. */ class result_file_to_pdf implements pts_option_interface { const doc_section = 'Result Management'; const doc_description = 'This option will read a saved test results file and output the system hardware and software information along with the results to a PDF file.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function run($r) { if(is_file('/usr/share/php/fpdf/fpdf.php')) { include_once('/usr/share/php/fpdf/fpdf.php'); } else { echo PHP_EOL . 'The FPDF library must be installed.' . PHP_EOL; return false; } $_REQUEST['force_format'] = 'PNG'; // Force to PNG renderer $_REQUEST['svg_dom_gd_no_interlacing'] = true; // Otherwise FPDF will fail pts_client::generate_result_file_graphs($r[0], PTS_SAVE_RESULTS_PATH . $r[0] . '/'); $result_file = new pts_result_file($r[0]); $pdf = new pts_pdf_template($result_file->get_title(), null); $pdf->AddPage(); $pdf->Image(PTS_CORE_STATIC_PATH . 'images/pts-308x160.png', 69, 85, 73, 38); $pdf->Ln(120); $pdf->WriteStatementCenter('www.phoronix-test-suite.com'); $pdf->Ln(15); $pdf->WriteBigHeaderCenter($result_file->get_title()); $pdf->WriteText($result_file->get_description()); $pdf->AddPage(); $pdf->Ln(15); $identifiers = $result_file->get_system_identifiers(); $hardware_r = $result_file->get_system_hardware(); $software_r = $result_file->get_system_software(); $notes_r = $result_file->get_system_notes(); $tests = $result_file->get_test_titles(); $pdf->SetSubject($result_file->get_title() . ' Benchmarks'); $pdf->SetKeywords(implode(', ', $identifiers)); $pdf->WriteHeader('Test Systems:'); for($i = 0; $i < count($identifiers); $i++) { $pdf->WriteMiniHeader($identifiers[$i]); $pdf->WriteText($hardware_r[$i]); $pdf->WriteText($software_r[$i]); //$pdf->WriteText($notes_r[$i]); } /* if(count($identifiers) > 1 && is_file(PTS_SAVE_RESULTS_PATH . $r[0] . '/result-graphs/overview.jpg')) { $pdf->AddPage(); $pdf->Ln(100); $pdf->Image(PTS_SAVE_RESULTS_PATH . $r[0] . '/result-graphs/overview.jpg', 15, 40, 180); } */ $pdf->AddPage(); $placement = 1; for($i = 1; $i <= count($tests); $i++) { if(is_file(PTS_SAVE_RESULTS_PATH . $r[0] . '/result-graphs/' . $i . '.png')) { $pdf->Ln(100); $pdf->Image(PTS_SAVE_RESULTS_PATH . $r[0] . '/result-graphs/' . $i . '.png', 50, 40 + (($placement - 1) * 120), 120); } if($placement == 2) { $placement = 0; if($i != count($tests)) { $pdf->AddPage(); } } $placement++; } // To save: /* $pdf_file = 'SAVE_TO'; if(substr($pdf_file, -4) != '.pdf') { $pdf_file .= '.pdf'; } */ $pdf_file = pts_client::user_home_directory() . $r[0] . '.pdf'; $pdf->Output($pdf_file); echo PHP_EOL . 'Saved To: ' . $pdf_file . PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/rename_identifier_in_result_file.php0000644000175000017500000000507112151406453027424 0ustar michaelmichael. */ class rename_identifier_in_result_file implements pts_option_interface { const doc_section = 'Result Management'; const doc_description = 'This option is used if you wish to change the name of the identifier in a test results file that is shown in the Phoronix Test Suite Results Viewer and the contained graphs.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function run($r) { $result = $r[0]; $result_file = new pts_result_file($result); $result_file_identifiers = $result_file->get_system_identifiers(); $rename_identifier = pts_user_io::prompt_text_menu('Select the test run to rename', $result_file_identifiers); $rename_identifier_new = pts_user_io::prompt_user_input('Enter the new identifier'); $merge_selects = array(); foreach($result_file_identifiers as $identifier) { $this_merge_select = new pts_result_merge_select($result, $identifier); if($identifier == $rename_identifier && $rename_identifier != $rename_identifier_new) { $this_merge_select->rename_identifier($rename_identifier_new); } array_push($merge_selects, $this_merge_select); } foreach(array('test-logs', 'system-logs', 'installation-logs') as $dir_name) { if(is_dir(PTS_SAVE_RESULTS_PATH . $r[0] . '/' . $dir_name . '/' . $rename_identifier)) { rename(PTS_SAVE_RESULTS_PATH . $r[0] . '/' . $dir_name . '/' . $rename_identifier, PTS_SAVE_RESULTS_PATH . $r[0] . '/' . $dir_name . '/' . $rename_identifier_new); } } $extract_result = pts_merge::merge_test_results_array($merge_selects); pts_client::save_test_result($r[0] . '/composite.xml', $extract_result); pts_client::display_web_page(PTS_SAVE_RESULTS_PATH . $r[0] . '/index.html'); } } ?> phoronix-test-suite/pts-core/commands/remove_result.php0000644000175000017500000000245111643042661023564 0ustar michaelmichael. */ class remove_result implements pts_option_interface { const doc_section = 'Result Management'; const doc_description = 'This option will permanently remove the saved file set that is set as the first argument.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_result_file', 'is_test_result_file'), null) ); } public static function run($r) { pts_client::remove_saved_result_file($r[0]); echo PHP_EOL . $r[0] . ' was removed.' . PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/remove_installed_test.php0000644000175000017500000000320111643042661025256 0ustar michaelmichael. */ class remove_installed_test implements pts_option_interface { const doc_section = 'Test Installation'; const doc_description = 'This option will permanently remove a installed test by the Phoronix Test Suite.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_test_profile', 'is_test_profile'), null) ); } public static function run($r) { $test_profile = new pts_test_profile($r[0]); if($test_profile->is_test_installed() == false) { echo PHP_EOL . 'This test is not installed.' . PHP_EOL; return false; } if(pts_user_io::prompt_bool_input('Are you sure you wish to remove the test ' . $test_profile, false)) { pts_client::remove_installed_test($test_profile); echo PHP_EOL . $test_profile . ' has been removed.' . PHP_EOL; } else { echo PHP_EOL; } } } ?> phoronix-test-suite/pts-core/commands/rebuild_composite_xml.php0000644000175000017500000000332411643042661025261 0ustar michaelmichael. */ class rebuild_composite_xml implements pts_option_interface { const doc_section = 'Other'; const doc_description = 'This option can be used to rebuild your composite XML file in the event that the main result file was corrupted and the test-X.xml files are still present in the result file directory.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function run($r) { $identifier = $r[0]; $test_xml_files = pts_file_io::glob(PTS_SAVE_RESULTS_PATH . $identifier . '/test-*.xml'); if(count($test_xml_files) == 0) { echo PHP_EOL . 'No test XML data was found.' . PHP_EOL; return false; } pts_client::save_test_result($identifier . '/composite.xml', pts_merge::merge_test_results_array($test_xml_files)); pts_client::regenerate_graphs($identifier, 'The ' . $identifier . ' result file XML has been rebuilt.'); } } ?> phoronix-test-suite/pts-core/commands/pts_version.php0000644000175000017500000000224011643042661023240 0ustar michaelmichael. */ class pts_version implements pts_option_interface { const doc_section = 'Other'; const doc_use_alias = 'version'; const doc_description = 'This option will display the Phoronix Test Suite client version.'; public static function command_aliases() { return array('version'); } public static function run($r) { echo PHP_EOL . pts_title(true) . PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/openbenchmarking_launcher.php0000644000175000017500000000440011643042661026060 0ustar michaelmichael. */ class openbenchmarking_launcher implements pts_option_interface { const doc_section = 'OpenBenchmarking.org'; const doc_description = 'This option is called automatically with the .openbenchmarking MIME file extension support for launching OpenBenchmarking.org operations.'; public static function run($r) { if(isset($r[0]) && strpos($r[0], '.openbenchmarking') !== false && is_readable($r[0])) { // OpenBenchmarking.org launcher $dom = new DOMDocument(); $dom->loadHTMLFile($r[0]); $requires_core_version = self::read_openbenchmarking_dom($dom, 'requires_core_version', PTS_CORE_VERSION); if(PTS_CORE_VERSION < $requires_core_version) { echo PHP_EOL . 'An incompatible OpenBenchmarking.org file was provided. You must upgrade the Phoronix Test Suite installation.' . PHP_EOL; return false; } $payload_type = self::read_openbenchmarking_dom($dom, 'payload_type'); $payload = self::read_openbenchmarking_dom($dom, 'payload'); switch($payload_type) { case 'benchmark': $to_benchmark = explode(' ', $payload); pts_test_installer::standard_install($to_benchmark); pts_test_run_manager::standard_run($to_benchmark); break; } } } protected static function read_openbenchmarking_dom(&$dom, $id, $fallback = false) { $tag = $dom->getElementById($id); if($tag instanceof DOMElement && $tag->tagName == 'input') { $value = $tag->getAttribute('value'); } else { $value = $fallback; } return $value; } } ?> phoronix-test-suite/pts-core/commands/network_setup.php0000644000175000017500000000405511643042661023604 0ustar michaelmichael. */ class network_setup implements pts_option_interface { const doc_section = 'Other'; const doc_description = 'This option allows the user to configure how the Phoronix Test Suite connects to OpenBenchmarking.org and other web-services. Connecting through an HTTP proxy can be configured through this option.'; public static function run($r) { pts_client::$display->generic_heading('Network Setup'); if(!pts_user_io::prompt_bool_input('Configure the Phoronix Test Suite to use a HTTP proxy', false)) { return false; } $proxy_address = pts_user_io::prompt_user_input('Enter IP address / server name of proxy'); $proxy_port = pts_user_io::prompt_user_input('Enter TCP port for proxy server'); echo PHP_EOL . 'Testing Proxy Server (' . $proxy_address . ':' . $proxy_port . ')' . PHP_EOL; if(pts_network::http_get_contents('http://www.phoronix-test-suite.com/PTS', $proxy_address, $proxy_port) == 'PTS') { echo PHP_EOL . 'Proxy Setup Completed; Storing Network Settings.' . PHP_EOL; pts_config::user_config_generate(array( 'PhoronixTestSuite/Options/Networking/ProxyAddress' => $proxy_address, 'PhoronixTestSuite/Options/Networking/ProxyPort' => $proxy_port )); } else { echo PHP_EOL . 'Proxy Setup Failed.' . PHP_EOL; } } } ?> phoronix-test-suite/pts-core/commands/module_setup.php0000644000175000017500000000637211643042661023404 0ustar michaelmichael. */ class module_setup implements pts_option_interface { const doc_section = 'Modules'; const doc_description = 'This option will allow you to configure all available end-user options for a Phoronix Test Suite module. These options are then stored within the user\'s configuration file. Not all modules may have options that can be configured by the end-user.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_module', 'is_module'), null) ); } public static function run($r) { $module = strtolower($r[0]); $pre_message = null; if(!class_exists($module)) { pts_module_manager::load_module($module); } $module_name = pts_module_manager::module_call($module, 'module_name'); $module_description = pts_module_manager::module_call($module, 'module_description'); $module_setup = pts_module_manager::module_call($module, 'module_setup'); pts_client::$display->generic_heading($module_name . ' Module Configuration'); echo $module_description . PHP_EOL; if(count($module_setup) == 0) { echo PHP_EOL . 'There are no options available for configuring with the ' . $module . ' module.' . PHP_EOL; } else { if(($module_presets = pts_client::read_env('PTS_MODULE_SETUP')) != false) { $module_presets = pts_client::parse_value_string_double_identifier($module_presets); } $set_options = array(); foreach($module_setup as $module_option) { if($module_option instanceOf pts_module_option) { $option_identifier = $module_option->get_identifier(); if(isset($module_presets[$module][$option_identifier]) && $module_option->is_supported_value($module_presets[$module][$option_identifier])) { echo PHP_EOL . $module_option->get_formatted_question(); echo $module_presets[$module][$option_identifier] . PHP_EOL; $input = $module_presets[$module][$option_identifier]; } else { do { echo PHP_EOL . $module_option->get_formatted_question(); $input = pts_user_io::read_user_input(); } while(!$module_option->is_supported_value($input)); } if(empty($input)) { $input = $module_option->get_default_value(); } $set_options[$option_identifier] = $input; } } $set_options = pts_module_manager::module_call($module, 'module_setup_validate', $set_options); if(!empty($set_options)) { pts_module::module_config_save($module, $set_options); } } echo PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/merge_results.php0000644000175000017500000000413311643042661023550 0ustar michaelmichael. */ class merge_results implements pts_option_interface { const doc_section = 'Result Management'; const doc_description = 'This option will manually merge multiple sets of test results generated by the Phoronix Test Suite.'; public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_types', 'is_result_file'), null) ); } public static function run($r) { $result_files_to_merge = array(); foreach($r as $result_file) { if(pts_types::is_result_file($result_file)) { array_push($result_files_to_merge, $result_file); } } if(count($result_files_to_merge) < 2) { echo PHP_EOL . 'At least two saved result names must be supplied.'; return false; } do { $rand_file = rand(1000, 9999); $merge_to_file = 'merge-' . $rand_file . '/'; } while(is_dir(PTS_SAVE_RESULTS_PATH . $merge_to_file)); $merge_to_file .= 'composite.xml'; // Merge Results $merged_results = call_user_func(array('pts_merge', 'merge_test_results_array'), $result_files_to_merge); pts_client::save_test_result($merge_to_file, $merged_results); echo 'Merged Results Saved To: ' . PTS_SAVE_RESULTS_PATH . $merge_to_file . PHP_EOL . PHP_EOL; pts_client::display_web_page(PTS_SAVE_RESULTS_PATH . dirname($merge_to_file) . '/index.html'); } } ?> phoronix-test-suite/pts-core/commands/list_saved_results.php0000644000175000017500000000341211643042661024605 0ustar michaelmichael. */ class list_saved_results implements pts_option_interface { const doc_section = 'Information'; const doc_description = 'This option will list all of the saved test results found on the system.'; public static function command_aliases() { return array('list_results', 'list_test_results'); } public static function run($r) { $saved_results = pts_client::saved_test_results(); pts_client::$display->generic_heading(count($saved_results) . ' Saved Results'); if(count($saved_results) > 0) { foreach($saved_results as $saved_results_identifier) { $result_file = new pts_result_file($saved_results_identifier); if(($title = $result_file->get_title()) != null) { echo sprintf('Saved Name: %-18ls Title: %-18ls', $saved_results_identifier, $title) . PHP_EOL; foreach($result_file->get_system_identifiers() as $id) { if(!empty($id)) { echo "\t" . '- ' . $id . PHP_EOL; } } echo PHP_EOL; } } } } } ?> phoronix-test-suite/pts-core/commands/list_possible_dependencies.php0000644000175000017500000000253011643042661026250 0ustar michaelmichael. */ class list_possible_dependencies implements pts_option_interface { const doc_section = 'Information'; const doc_description = 'This option will list all of the packages / external test dependencies that are are potentially used by the Phoronix Test Suite.'; public static function run($r) { $all_dependencies = pts_external_dependencies::all_dependency_titles(); pts_client::$display->generic_heading(count($all_dependencies) . ' External Dependencies Available'); echo pts_user_io::display_text_list($all_dependencies); echo PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/list_missing_dependencies.php0000644000175000017500000000271111643042661026102 0ustar michaelmichael. */ class list_missing_dependencies implements pts_option_interface { const doc_section = 'Information'; const doc_description = 'This option will list all of the packages / external test dependencies that are missing from the system that the Phoronix Test Suite may potentially need by select test profiles.'; public static function run($r) { $missing_titles = pts_external_dependencies::missing_dependency_titles(); pts_client::$display->generic_heading(count($missing_titles) . ' of ' . count(pts_external_dependencies::all_dependency_names()) . ' External Dependencies Missing'); echo pts_user_io::display_text_list($missing_titles); echo PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/list_installed_tests.php0000644000175000017500000000273311643042661025130 0ustar michaelmichael. */ class list_installed_tests implements pts_option_interface { const doc_section = 'Information'; const doc_description = 'This option will list all test profiles that are currently installed on the system.'; public static function run($r) { $installed_tests = pts_tests::installed_tests(); pts_client::$display->generic_heading(count($installed_tests) . ' Tests Installed'); if(count($installed_tests) > 0) { foreach($installed_tests as $identifier) { $test_profile = new pts_test_profile($identifier); $name = $test_profile->get_title(); if($name != false) { echo sprintf('%-26ls - %-30ls' . PHP_EOL, $identifier, $name); } } } } } ?> phoronix-test-suite/pts-core/commands/list_installed_dependencies.php0000644000175000017500000000271511643042661026414 0ustar michaelmichael. */ class list_installed_dependencies implements pts_option_interface { const doc_section = 'Information'; const doc_description = 'This option will list all of the packages / external test dependencies that are already installed on the system that the Phoronix Test Suite may potentially depend upon by test profiles.'; public static function run($r) { $installed_titles = pts_external_dependencies::installed_dependency_titles(); pts_client::$display->generic_heading(count($installed_titles) . ' of ' . count(pts_external_dependencies::all_dependency_names()) . ' External Dependencies Installed'); echo pts_user_io::display_text_list($installed_titles); } } ?> phoronix-test-suite/pts-core/commands/list_available_virtual_suites.php0000644000175000017500000000302611643042661027005 0ustar michaelmichael. */ class list_available_virtual_suites implements pts_option_interface { const doc_section = 'Information'; const doc_description = 'This option will list all available virtual test suites that can be dynamically created based upon the available tests from enabled OpenBenchmarking.org repositories.'; public static function run($r) { pts_client::$display->generic_heading('Available Virtual Suites'); foreach(pts_virtual_test_suite::available_virtual_suites() as $virtual_suite) { $size = count($virtual_suite->get_contained_test_profiles()); if($size > 0) { echo sprintf('%-22ls - %-32ls %-9ls', $virtual_suite->get_identifier(), $virtual_suite->get_title(), $size . ' Tests') . PHP_EOL; } } echo PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/install_dependencies.php0000644000175000017500000000406511643042661025050 0ustar michaelmichael. */ class install_dependencies implements pts_option_interface { const doc_section = 'Test Installation'; const doc_description = 'This option will install the external dependencies needed by the selected test(s) using the distribution\'s package management system. For example, some tests depend upon GCC for compiling code. If GCC is not detected on the system, the Phoronix Test Suite will attempt to install GCC using the distribution\'s package management system. If you are running this command as a local user, you may be prompted for the root password while the process is running. For unsupported distributions, the dependency names will be displayed along with common names for the package. The install-dependencies option needs to be supplied with the test name or suite as an argument. When using the install option, the external dependencies are automatically checked.'; public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_types', 'identifier_to_object'), null) ); } public static function run($r) { $test_profiles = pts_types::identifiers_to_test_profile_objects($r, true, true); //pts_client::set_test_flags(pts_c::auto_mode); pts_external_dependencies::install_dependencies($test_profiles); } } ?> phoronix-test-suite/pts-core/commands/force_install.php0000644000175000017500000000275711643042661023526 0ustar michaelmichael. */ class force_install implements pts_option_interface { const doc_section = 'Asset Creation'; const doc_description = 'This option will force the installation (or re-installation) of a test or suite. The arguments and process is similar to the install option but even if the test is installed, the entire installation process will automatically be executed. This option is generally used when debugging a test installation problem.'; public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_types', 'identifier_to_object'), null) ); } public static function run($r) { pts_test_installer::standard_install($r, pts_c::force_install); } } ?> phoronix-test-suite/pts-core/commands/finish_run.php0000644000175000017500000000564411643042661023044 0ustar michaelmichael. */ class finish_run implements pts_option_interface { const doc_section = 'Testing'; const doc_description = 'This option can be used if a test run had not properly finished running all tests within a saved results file. Using this option when specifying a saved results file where all tests had not completed will attempt to finish testing on the remaining tests where there are missing results.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_result_file', 'is_test_result_file'), null) ); } public static function run($args) { $save_name = $args[0]; $result_file = new pts_result_file($args[0]); $system_identifiers = $result_file->get_system_identifiers(); $test_positions = array(); $pos = 0; foreach($result_file->get_result_objects() as $result_object) { $this_result_object_identifiers = $result_object->test_result_buffer->get_identifiers(); foreach($system_identifiers as $system_identifier) { if(!in_array($system_identifier, $this_result_object_identifiers)) { if(!isset($test_positions[$system_identifier])) { $test_positions[$system_identifier] = array(); } array_push($test_positions[$system_identifier], $pos); } } $pos++; } $incomplete_identifiers = array_keys($test_positions); if(count($incomplete_identifiers) == 0) { echo PHP_EOL . 'It appears that there are no incomplete test results within this saved file.' . PHP_EOL . PHP_EOL; return false; } $selected = pts_user_io::prompt_text_menu('Select which incomplete test run you would like to finish', $incomplete_identifiers); // Now run it if(pts_test_run_manager::initial_checks($args[0]) == false) { return false; } $test_run_manager = new pts_test_run_manager(pts_c::is_recovering); // Load the tests to run if($test_run_manager->load_result_file_to_run($save_name, $selected, $result_file, $test_positions[$selected]) == false) { return false; } // Run the actual tests $test_run_manager->pre_execution_process(); $test_run_manager->call_test_runs(); $test_run_manager->post_execution_process(); } } ?> phoronix-test-suite/pts-core/commands/dump_possible_options.php0000644000175000017500000000250511643042661025311 0ustar michaelmichael. */ class dump_possible_options implements pts_option_interface { public static function run($r) { $options = array(); foreach(pts_file_io::glob(PTS_COMMAND_PATH . '*.php') as $option_php) { $name = str_replace('_', '-', basename($option_php, '.php')); if(!in_array(pts_strings::first_in_string($name, '-'), array('dump', 'debug', 'task'))) { array_push($options, $name); } } $is_true = isset($r[0]) && $r[0] == 'TRUE'; echo implode($is_true ? ' ' : PHP_EOL, $options) . ($is_true ? null : PHP_EOL); } } ?> phoronix-test-suite/pts-core/commands/dump_phodevi_smart_cache.php0000644000175000017500000000235111643042661025704 0ustar michaelmichael. */ class dump_phodevi_smart_cache implements pts_option_interface { public static function run($r) { $pso = pts_storage_object::recover_from_file(PTS_CORE_STORAGE); $phodevi_sc = $pso->read_object('phodevi_smart_cache'); foreach($phodevi_sc as $index => $element) { if($index != 'phodevi_cache') { echo $index . ': ' . $element . PHP_EOL; } } echo PHP_EOL; print_r($phodevi_sc->read_cache()); echo PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/dump_core_storage.php0000644000175000017500000000257711643042661024403 0ustar michaelmichael. */ class dump_core_storage implements pts_option_interface { public static function run($r) { pts_client::$display->generic_heading('Core Storage'); $pso = pts_storage_object::recover_from_file(PTS_CORE_STORAGE); foreach($pso->get_objects() as $pso_index => $pso_object) { if($pso_index != 'phodevi_smart_cache') { echo $pso_index . ': '; if(is_array($pso_object)) { foreach($pso_object as $key => $element) { echo PHP_EOL . "\t" . $key . ': ' . $element; } } else { echo $pso_object; } echo PHP_EOL; } } echo PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/default_benchmark.php0000644000175000017500000000271411643042661024331 0ustar michaelmichael. */ class default_benchmark implements pts_option_interface { const doc_section = 'Batch Testing'; const doc_description = 'This option will install the selected test(s) (if needed) and will proceed to run the test(s) in the defaults mode. This option is equivalent to running phoronix-test-suite with the install option followed by the default-run option.'; public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_types', 'identifier_to_object'), null) ); } public static function run($r) { pts_test_installer::standard_install($r); pts_test_run_manager::standard_run($r, pts_c::defaults_mode); } } ?> phoronix-test-suite/pts-core/commands/debug_test_download_links.php0000644000175000017500000000376411643042661026115 0ustar michaelmichael. */ class debug_test_download_links implements pts_option_interface { const doc_section = 'Asset Creation'; const doc_description = 'This option will check all download links within the specified test profile(s) to ensure there are no broken URLs.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_test_or_suite'), null) ); } public static function run($r) { foreach(pts_types::identifiers_to_test_profile_objects($r, true, true) as $test_profile) { echo 'Checking: ' . $test_profile . PHP_EOL; foreach(pts_test_install_request::read_download_object_list($test_profile) as $test_file_download) { foreach($test_file_download->get_download_url_array() as $url) { $stream_context = pts_network::stream_context_create(); stream_context_set_params($stream_context, array('notification' => 'pts_stream_status_callback')); $file_pointer = @fopen($url, 'r', false, $stream_context); //fread($file_pointer, 1024); if($file_pointer == false) { echo PHP_EOL . 'DOWNLOAD: ' . $test_file_download->get_filename() . ' / ' . $url . PHP_EOL; } else { @fclose($file_pointer); } } } } } } ?> phoronix-test-suite/pts-core/commands/reorder_result_file.php0000644000175000017500000000514412151406356024732 0ustar michaelmichael. */ class reorder_result_file implements pts_option_interface { const doc_section = 'Result Management'; const doc_description = 'This option is used if you wish to change the order in which test results are shown in the Phoronix Test Suite Results Viewer and the contained graphs. The user must specify a saved results file and then they will be prompted to select the results identifiers one at a time in the order they would like them to be displayed from left to right.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function run($args) { $result = $args[0]; $result_file = new pts_result_file($result); $result_file_identifiers = $result_file->get_system_identifiers(); if(count($result_file_identifiers) < 2) { echo PHP_EOL . 'There are not multiple test runs in this result file.' . PHP_EOL; return false; } $extract_selects = array(); echo PHP_EOL . 'Enter The New Order To Display The New Results, From Left To Right.' . PHP_EOL; do { $extract_identifier = pts_user_io::prompt_text_menu('Select the test run to be showed next', $result_file_identifiers); array_push($extract_selects, new pts_result_merge_select($result, $extract_identifier)); $old_identifiers = $result_file_identifiers; $result_file_identifiers = array(); foreach($old_identifiers as $identifier) { if($identifier != $extract_identifier) { array_push($result_file_identifiers, $identifier); } } } while(count($result_file_identifiers) > 0); $ordered_result = pts_merge::merge_test_results_array($extract_selects); pts_client::save_test_result($args[0] . '/composite.xml', $ordered_result); pts_client::display_web_page(PTS_SAVE_RESULTS_PATH . $args[0] . '/index.html'); } } ?> phoronix-test-suite/pts-core/commands/clone_openbenchmarking_result.php0000644000175000017500000000372711643042661026770 0ustar michaelmichael. */ class clone_openbenchmarking_result implements pts_option_interface { const doc_section = 'OpenBenchmarking.org'; const doc_use_alias = 'clone-result'; const doc_description = 'This option will download a local copy of a file that was saved to OpenBenchmarking.org, as long as a valid public ID is supplied. More than one ID can be specified and the results will then be merged.'; public static function command_aliases() { return array('clone', 'clone_result'); } public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_openbenchmarking', 'is_openbenchmarking_result_id'), null) ); } public static function run($args) { $result_files = array(); foreach($args as $id) { $xml = pts_openbenchmarking::clone_openbenchmarking_result($id, true); array_push($result_files, new pts_result_file($xml)); } $writer = new pts_result_file_writer(null); pts_merge::merge_test_results_process($writer, $result_files); pts_client::save_test_result($args[0] . '/composite.xml', $writer->get_xml(), true); echo PHP_EOL . 'Result Saved To: ' . PTS_SAVE_RESULTS_PATH . $args[0] . '/composite.xml' . PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/batch_setup.php0000644000175000017500000000703011643042661023170 0ustar michaelmichael. */ class batch_setup implements pts_option_interface { const doc_section = 'Batch Testing'; const doc_description = 'This option is used to configure the batch mode options for the Phoronix Test Suite, which is subsequently written to the user configuration file. Among the options are whether to automatically upload the test results to OpenBenchmarking.org and prompting for the saved file name.'; public static function run($r) { echo PHP_EOL . 'These are the default configuration options for when running the Phoronix Test Suite in a batch mode (i.e. running phoronix-test-suite batch-benchmark universe). Running in a batch mode is designed to be as autonomous as possible, except for where you\'d like any end-user interaction.' . PHP_EOL . PHP_EOL; $batch_options = array(); $batch_options['PhoronixTestSuite/Options/BatchMode/SaveResults'] = pts_config::bool_to_string(pts_user_io::prompt_bool_input('Save test results when in batch mode', true)); if($batch_options['PhoronixTestSuite/Options/BatchMode/SaveResults'] == 'TRUE') { $batch_options['PhoronixTestSuite/Options/BatchMode/OpenBrowser'] = pts_config::bool_to_string(pts_user_io::prompt_bool_input('Open the web browser automatically when in batch mode', false)); $batch_options['PhoronixTestSuite/Options/BatchMode/UploadResults'] = pts_config::bool_to_string(pts_user_io::prompt_bool_input('Auto upload the results to OpenBenchmarking.org', true)); $batch_options['PhoronixTestSuite/Options/BatchMode/PromptForTestIdentifier'] = pts_config::bool_to_string(pts_user_io::prompt_bool_input('Prompt for test identifier', true)); $batch_options['PhoronixTestSuite/Options/BatchMode/PromptForTestDescription'] = pts_config::bool_to_string(pts_user_io::prompt_bool_input('Prompt for test description', true)); $batch_options['PhoronixTestSuite/Options/BatchMode/PromptSaveName'] = pts_config::bool_to_string(pts_user_io::prompt_bool_input('Prompt for saved results file-name', true)); } else { $batch_options['PhoronixTestSuite/Options/BatchMode/OpenBrowser'] = 'FALSE'; $batch_options['PhoronixTestSuite/Options/BatchMode/UploadResults'] = 'FALSE'; $batch_options['PhoronixTestSuite/Options/BatchMode/PromptForTestIdentifier'] = 'FALSE'; $batch_options['PhoronixTestSuite/Options/BatchMode/PromptForTestDescription'] = 'FALSE'; $batch_options['PhoronixTestSuite/Options/BatchMode/PromptSaveName'] = 'FALSE'; } $batch_options['PhoronixTestSuite/Options/BatchMode/RunAllTestCombinations'] = pts_config::bool_to_string(pts_user_io::prompt_bool_input('Run all test options', true)); $batch_options['PhoronixTestSuite/Options/BatchMode/Configured'] = 'TRUE'; pts_config::user_config_generate($batch_options); echo PHP_EOL . 'Batch settings saved.' . PHP_EOL . PHP_EOL; } } ?> phoronix-test-suite/pts-core/commands/show_result.php0000644000175000017500000000304211754656115023254 0ustar michaelmichael. */ class show_result implements pts_option_interface { const doc_section = 'Result Management'; const doc_description = 'Open up the test results in the Phoronix Test Suite Result Viewer or on OpenBenchmarking.org.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function invalid_command($passed_args = null) { pts_tests::recently_saved_results(); } public static function run($r) { $URL = PTS_SAVE_RESULTS_PATH . $r[0]; if(!is_dir($URL . '/result-graphs/')) { pts_client::generate_result_file_graphs($r[0], PTS_SAVE_RESULTS_PATH . $r[0] . '/'); } pts_client::display_web_page($URL . '/index.html', null, false, true); } } ?> phoronix-test-suite/pts-core/commands/detailed_system_info.php0000644000175000017500000000450011754655762025077 0ustar michaelmichael. */ class detailed_system_info implements pts_option_interface { const doc_section = 'System'; const doc_description = 'Display detailed information about the installed system hardware and software information as detected by the Phoronix Test Suite Phodevi Library.'; public static function run($r) { pts_client::$display->generic_heading('System Information'); echo 'Hardware:' . PHP_EOL . phodevi::system_hardware(true) . PHP_EOL . PHP_EOL; echo 'Software:' . PHP_EOL . phodevi::system_software(true) . PHP_EOL . PHP_EOL; // // Processor Information // $cpu_flags = phodevi_cpu::get_cpu_flags(); echo PHP_EOL . 'PROCESSOR:' . PHP_EOL . PHP_EOL; echo 'Core Count: ' . phodevi_cpu::cpuinfo_core_count() . PHP_EOL; echo 'Thread Count: ' . phodevi_cpu::cpuinfo_thread_count() . PHP_EOL; echo 'Cache Size: ' . phodevi_cpu::cpuinfo_cache_size() . ' KB' . PHP_EOL; echo 'Instruction Set Extensions: ' . phodevi_cpu::instruction_set_extensions() . PHP_EOL; echo 'AES Encryption: ' . ($cpu_flags & phodevi_cpu::get_cpu_feature_constant('aes') ? 'YES' : 'NO') . PHP_EOL; echo 'Energy Performance Bias: ' . ($cpu_flags & phodevi_cpu::get_cpu_feature_constant('epb') ? 'YES' : 'NO') . PHP_EOL; echo 'Virtualization: ' . (phodevi_cpu::virtualization_technology() ? phodevi_cpu::virtualization_technology() : 'NO') . PHP_EOL; // Other info foreach(pts_test_run_manager::pull_test_notes(true) as $test_note_head => $test_note) { echo ucwords(str_replace('-', ' ', $test_note_head)) . ': ' . $test_note . PHP_EOL; } } } ?> phoronix-test-suite/pts-core/commands/batch_install.php0000644000175000017500000000270511643042661023502 0ustar michaelmichael. */ class batch_install implements pts_option_interface { const doc_section = 'Batch Testing'; const doc_description = 'If you wish to run the install process in the Phoronix Test Suite batch mode but do not wish to run any tests at this time. Running the install process in the batch mode will use the default values and not prompt the user of any possible options, to ensure the process is fully automated.'; public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_types', 'identifier_to_object'), null) ); } public static function run($r) { pts_test_installer::standard_install($r, pts_c::batch_mode); } } ?> phoronix-test-suite/pts-core/commands/batch_benchmark.php0000644000175000017500000000255411643042661023770 0ustar michaelmichael. */ class batch_benchmark implements pts_option_interface { const doc_section = 'Batch Testing'; const doc_description = 'This option and its arguments are equivalent to the benchmark option, but the process will be run in the Phoronix Test Suite batch mode.'; public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_types', 'identifier_to_object'), null) ); } public static function run($r) { pts_test_installer::standard_install($r, pts_c::batch_mode); pts_test_run_manager::standard_run($r, pts_c::batch_mode); } } ?> phoronix-test-suite/pts-core/commands/analyze_image_delta.php0000644000175000017500000001142111643042661024644 0ustar michaelmichael. */ class analyze_image_delta implements pts_option_interface { const doc_section = 'Result Analytics'; const doc_description = 'This option will analyze a test result file if it contains any test results that produced an image quality comparison (IQC) and will render image deltas illustrating the difference between images from two test results.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function run($args) { $result = $args[0]; $result_file = new pts_result_file($result); $result_file_identifiers = $result_file->get_system_identifiers(); if(count($result_file_identifiers) < 2) { echo PHP_EOL . 'There are not multiple test runs in this result file.' . PHP_EOL; return false; } $base_identifier = pts_user_io::prompt_text_menu('Select the base test run', $result_file_identifiers); $base_select = new pts_result_merge_select($result, $base_identifier); $compare_identifier = pts_user_io::prompt_text_menu('Select the test run to compare', $result_file_identifiers); $compare_select = new pts_result_merge_select($result, $compare_identifier); do { $extract_to = 'iqc-analyze-' . rand(100, 999); } while(is_dir(PTS_SAVE_RESULTS_PATH . $extract_to)); $extract_result = pts_merge::merge_test_results($base_select, $compare_select); pts_client::save_test_result($extract_to . '/composite.xml', $extract_result); $compare_file = new pts_result_file($extract_to); $result_file_writer = new pts_result_file_writer('Image Delta'); foreach($compare_file->get_result_objects() as $result_object) { if($result_object->test_profile->get_display_format() != 'IMAGE_COMPARISON') { continue; } $base_result = null; $compare_result = null; foreach($result_object->test_result_buffer->get_buffer_items() as $buffer_item) { if($buffer_item->get_result_identifier() == $base_identifier && $base_result == null) { $base_result = $buffer_item->get_result_value(); } else if($buffer_item->get_result_identifier() == $compare_identifier && $compare_result == null) { $compare_result = $buffer_item->get_result_value(); } if($compare_result != null && $base_result != null) { break; } } if($compare_result == null || $base_result == null) { continue; } $base_img = imagecreatefromstring(base64_decode($base_result)); $compare_img = imagecreatefromstring(base64_decode($compare_result)); $delta_img = imagecreatefromstring(base64_decode($compare_result)); $img_width = imagesx($base_img); $img_height = imagesy($base_img); $img_changed = false; for($x = 0; $x < $img_width; $x++) { for($y = 0; $y < $img_height; $y++) { $base_image_color = pts_image::rgb_gd_color_at($base_img, $x, $y); $compare_image_color = pts_image::rgb_gd_color_at($compare_img, $x, $y); if($base_image_color == $compare_image_color || pts_image::rgb_int_diff($base_image_color, $compare_image_color) < 9) { if(($cords = pts_image::color_pixel_delta($base_img, $compare_img, $x, $y))) { $pixel_rgb = pts_image::rgb_gd_color_at($delta_img, $cords[0], $cords[1]); $color_invert = imagecolorresolve($delta_img, 255 - $pixel_rgb[0], 255 - $pixel_rgb[1], 255 - $pixel_rgb[2]); imagesetpixel($delta_img, $x, $y, $color_invert); $img_changed = true; } } } } if($img_changed) { imagepng($delta_img, PTS_SAVE_RESULTS_PATH . $extract_to . '/scratch.png'); $result_value = base64_encode(file_get_contents(PTS_SAVE_RESULTS_PATH . $extract_to . '/scratch.png', FILE_BINARY)); pts_file_io::unlink(PTS_SAVE_RESULTS_PATH . $extract_to . '/scratch.png'); $result_file_writer->add_result_from_result_object_with_value_string($result_object, $result_value); } } pts_client::save_result_file($result_file_writer, $extract_to); pts_client::display_web_page(PTS_SAVE_RESULTS_PATH . $extract_to . '/composite.xml'); } } ?> phoronix-test-suite/pts-core/commands/analyze_batch.php0000644000175000017500000000352011643042661023473 0ustar michaelmichael. */ class analyze_batch implements pts_option_interface { const doc_section = 'Result Analytics'; const doc_description = 'This option will analyze a batch results file and plot out the performance impact from the different options onto a line graph (i.e. to see the impact that changing the video resolution has on the system\'s performance).'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function run($args) { $base_file = $args[0]; do { $rand_file = rand(1000, 9999); $save_to = 'analyze-' . $rand_file . '/'; } while(is_dir(PTS_SAVE_RESULTS_PATH . $save_to)); $save_to .= 'composite.xml'; // Analyze Results $SAVED_RESULTS = pts_merge::generate_analytical_batch_xml($base_file); pts_client::save_test_result($save_to, $SAVED_RESULTS); echo 'Results Saved To: ' . PTS_SAVE_RESULTS_PATH . $save_to . PHP_EOL . PHP_EOL; pts_client::display_web_page(PTS_SAVE_RESULTS_PATH . dirname($save_to) . '/index.html'); } } ?> phoronix-test-suite/pts-core/commands/analyze_all_runs.php0000644000175000017500000000377611643042661024246 0ustar michaelmichael. */ class analyze_all_runs implements pts_option_interface { const doc_section = 'Result Analytics'; const doc_description = 'This option will generate a candlestick graph showing the distribution of results from all trial runs. The candlestick graph is similar to the Japanese candlestick charts used by the financial industry, except instead of representing stock data it is numerical result data from all trial runs.\n\nThe tip of the upper-wick represents the highest value of the test runs with the tip of the lower-wick representing the lowest value of all test runs. The upper-edge of the candle body represents the first or last run value and the lower-edge represents the first or last run value. Lastly, if the last run value is less than the first run value, the candle body is the same color as the graph background, otherwise the last run value is greater.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'is_result_file'), null) ); } public static function run($args) { pts_client::regenerate_graphs($args[0], 'The ' . $args[0] . ' result file graphs have been re-rendered to show all test runs.', array('graph_render_type' => 'CANDLESTICK')); } } ?> phoronix-test-suite/pts-core/commands/internal_run.php0000664000175000017500000000342312151410014023355 0ustar michaelmichael. */ class internal_run implements pts_option_interface { const doc_section = 'Batch Testing'; const doc_description = 'This option and its arguments pre-set the Phoronix Test Suite batch run mode with sane values for carrying out benchmarks in a semi-automated manner and without uploading any of the result data to the public OpenBenchmarking.org.'; public static function argument_checks() { return array( new pts_argument_check('VARIABLE_LENGTH', array('pts_types', 'identifier_to_object'), null) ); } public static function run($r) { pts_test_run_manager::set_batch_mode(array( 'UploadResults' => false, 'SaveResults' => true, 'PromptForTestDescription' => true, 'RunAllTestCombinations' => false, 'PromptSaveName' => true, 'PromptForTestIdentifier' => true, 'OpenBrowser' => true )); pts_test_run_manager::standard_run($r, pts_c::batch_mode); } public static function invalid_command($passed_args = null) { pts_tests::invalid_command_helper($passed_args); } } ?> phoronix-test-suite/pts-core/commands/info.php0000644000175000017500000001272512041517063021625 0ustar michaelmichael. */ class info implements pts_option_interface { const doc_section = 'Information'; const doc_description = 'This option will show details about the supplied test, suite, virtual suite, or result file.'; public static function argument_checks() { return array( new pts_argument_check(0, array('pts_types', 'identifier_to_object'), 'object') ); } public static function run($args) { echo PHP_EOL; if($args['object'] instanceof pts_test_suite) { pts_client::$display->generic_heading($args['object']->get_title()); echo 'Run Identifier: ' . $args['object']->get_identifier() . PHP_EOL; echo 'Suite Version: ' . $args['object']->get_version() . PHP_EOL; echo 'Maintainer: ' . $args['object']->get_maintainer() . PHP_EOL; echo 'Suite Type: ' . $args['object']->get_suite_type() . PHP_EOL; echo 'Unique Tests: ' . $args['object']->get_unique_test_count() . PHP_EOL; echo 'Suite Description: ' . $args['object']->get_description() . PHP_EOL; echo PHP_EOL; echo $args['object']->pts_format_contained_tests_string(); echo PHP_EOL; } else if($args['object'] instanceof pts_test_profile) { $test_title = $args['object']->get_title(); $test_version = $args['object']->get_app_version(); if(!empty($test_version)) { $test_title .= ' ' . $test_version; } pts_client::$display->generic_heading($test_title); echo 'Run Identifier: ' . $args['object']->get_identifier() . PHP_EOL; echo 'Profile Version: ' . $args['object']->get_test_profile_version() . PHP_EOL; echo 'Maintainer: ' . $args['object']->get_maintainer() . PHP_EOL; echo 'Test Type: ' . $args['object']->get_test_hardware_type() . PHP_EOL; echo 'Software Type: ' . $args['object']->get_test_software_type() . PHP_EOL; echo 'License Type: ' . $args['object']->get_license() . PHP_EOL; echo 'Test Status: ' . $args['object']->get_status() . PHP_EOL; echo 'Project Web-Site: ' . $args['object']->get_project_url() . PHP_EOL; if($args['object']->get_estimated_run_time() > 1) { echo 'Estimated Run-Time: ' . $args['object']->get_estimated_run_time() . ' Seconds' . PHP_EOL; } $download_size = $args['object']->get_download_size(); if(!empty($download_size)) { echo 'Download Size: ' . $download_size . ' MB' . PHP_EOL; } $environment_size = $args['object']->get_environment_size(); if(!empty($environment_size)) { echo 'Environment Size: ' . $environment_size . ' MB' . PHP_EOL; } echo PHP_EOL . 'Description: ' . $args['object']->get_description() . PHP_EOL; if($args['object']->test_installation != false) { $last_run = $args['object']->test_installation->get_last_run_date(); $last_run = $last_run == '0000-00-00' ? 'Never' : $last_run; $avg_time = $args['object']->test_installation->get_average_run_time(); $avg_time = !empty($avg_time) ? pts_strings::format_time($avg_time, 'SECONDS') : 'N/A'; $latest_time = $args['object']->test_installation->get_latest_run_time(); $latest_time = !empty($latest_time) ? pts_strings::format_time($latest_time, 'SECONDS') : 'N/A'; echo PHP_EOL . 'Test Installed: Yes' . PHP_EOL; echo 'Last Run: ' . $last_run . PHP_EOL; if($last_run != 'Never') { if($args['object']->test_installation->get_run_count() > 1) { echo 'Average Run-Time: ' . $avg_time . PHP_EOL; } echo 'Latest Run-Time: ' . $latest_time . PHP_EOL; echo 'Times Run: ' . $args['object']->test_installation->get_run_count() . PHP_EOL; } } else { echo PHP_EOL . 'Test Installed: No' . PHP_EOL; } $dependencies = $args['object']->get_dependencies(); if(!empty($dependencies) && !empty($dependencies[0])) { echo PHP_EOL . 'Software Dependencies:' . PHP_EOL; echo pts_user_io::display_text_list($args['object']->get_dependency_names()); } echo PHP_EOL; } else if($args['object'] instanceof pts_result_file) { echo 'Title: ' . $args['object']->get_title() . '\nIdentifier: ' . $args['object']->get_identifier() . PHP_EOL; echo PHP_EOL . 'Test Result Identifiers:' . PHP_EOL; echo pts_user_io::display_text_list($args['object']->get_system_identifiers()); if(count(($tests = $args['object']->get_unique_test_titles())) > 0) { echo PHP_EOL . 'Contained Tests:' . PHP_EOL; echo pts_user_io::display_text_list($tests); } echo PHP_EOL; } else if($args['object'] instanceof pts_virtual_test_suite) { pts_client::$display->generic_heading($args['object']->get_title()); echo 'Virtual Suite Description: ' . $args['object']->get_description() . PHP_EOL . PHP_EOL; foreach($args['object']->get_contained_test_profiles() as $test_profile) { echo '- ' . $test_profile . PHP_EOL; } echo PHP_EOL; } } } ?> phoronix-test-suite/documentation/man-pages/phoronix-test-suite.10000644000175000017500000004765212223157104025406 0ustar michaelmichael.TH phoronix-test-suite 1 "www.phoronix-test-suite.com" "4.8.3" .SH NAME phoronix-test-suite \- The Phoronix Test Suite is an extensible open-source platform for performing testing and performance evaluation. .SH SYNOPSIS .B phoronix-test-suite [options] .br .B phoronix-test-suite benchmark [test | suite] .SH DESCRIPTION The Phoronix Test Suite is the most comprehensive testing and benchmarking platform available for Linux, Solaris, Mac OS X, and BSD operating systems. The Phoronix Test Suite allows for carrying out tests in a fully automated manner from test installation to execution and reporting. All tests are meant to be easily reproducible, easy-to-use, and support fully automated execution. The Phoronix Test Suite is open-source under the GNU GPLv3 license and is developed by Phoronix Media in cooperation with partners. .SH OPTIONS .TP .SH TEST INSTALLATION .B install [Test | Suite | OpenBenchmarking.org ID | Test Result] ... This option will install the selected test(s) inside the testing environment directory). The install process from downloading of the test files to the installation is fully automated. The install option needs to be supplied with the test name or suite as an argument. Optionally, a OpenBenchmarking.org ID or the name of a saved results file can be supplied as well and the test(s) to install will automatically be extracted from that information. If the test is already installed and was run by the latest version of the installation process, no action will be taken. Multiple arguments can be supplied to install additional tests at the same time. .TP .B install-dependencies [Test | Suite | OpenBenchmarking.org ID | Test Result] ... This option will install the external dependencies needed by the selected test(s) using the distribution's package management system. For example, some tests depend upon GCC for compiling code. If GCC is not detected on the system, the Phoronix Test Suite will attempt to install GCC using the distribution's package management system. If you are running this command as a local user, you may be prompted for the root password while the process is running. For unsupported distributions, the dependency names will be displayed along with common names for the package. The install-dependencies option needs to be supplied with the test name or suite as an argument. When using the install option, the external dependencies are automatically checked. .TP .B make-download-cache This option will create a download cache for use by the Phoronix Test Suite. .TP .B remove-installed-test [Test] This option will permanently remove a installed test by the Phoronix Test Suite. .TP .SH TESTING .B auto-compare This option will autonomously determine the most relevant test(s) to run for any selected sub-system(s). The tests to run are determined via OpenBenchmarking.org integration with the global results pool. Related test results from OpenBenchmarking.org are also merged to provide a straight-forward and effective means of carrying out a system comparison. If wishing to find comparable results for any particular test profile(s), simply pass the test profile names as additional arguments to this command. .TP .B benchmark [Test | Suite | OpenBenchmarking.org ID | Test Result] ... This option will install the selected test(s) (if needed) and will proceed to run the test(s). This option is equivalent to running phoronix-test-suite with the install option followed by the run option. Multiple arguments can be supplied to run additional tests at the same time and save the results into one file. .TP .B finish-run [Test Result] This option can be used if a test run had not properly finished running all tests within a saved results file. Using this option when specifying a saved results file where all tests had not completed will attempt to finish testing on the remaining tests where there are missing results. .TP .B run [Test | Suite | OpenBenchmarking.org ID | Test Result] ... This option will run the selected test(s). .TP .B run-tests-in-suite This option can be used if you wish to run all of the tests found in a supplied suite, but you wish to re-configure each of the test options rather than using the defaults supplied by the suite. .TP .SH BATCH TESTING .B batch-benchmark [Test | Suite | OpenBenchmarking.org ID | Test Result] ... This option and its arguments are equivalent to the benchmark option, but the process will be run in the Phoronix Test Suite batch mode. .TP .B batch-install [Test | Suite | OpenBenchmarking.org ID | Test Result] ... If you wish to run the install process in the Phoronix Test Suite batch mode but do not wish to run any tests at this time. Running the install process in the batch mode will use the default values and not prompt the user of any possible options, to ensure the process is fully automated. .TP .B batch-run [Test | Suite | OpenBenchmarking.org ID | Test Result] ... This option and its arguments are equivalent to the run option, but the process will be run in the Phoronix Test Suite batch mode. .TP .B batch-setup This option is used to configure the batch mode options for the Phoronix Test Suite, which is subsequently written to the user configuration file. Among the options are whether to automatically upload the test results to OpenBenchmarking.org and prompting for the saved file name. .TP .B default-benchmark [Test | Suite | OpenBenchmarking.org ID | Test Result] ... This option will install the selected test(s) (if needed) and will proceed to run the test(s) in the defaults mode. This option is equivalent to running phoronix-test-suite with the install option followed by the default-run option. .TP .B default-run [Test | Suite | OpenBenchmarking.org ID | Test Result] ... This option will run the selected test(s). The name of the test or suite must be supplied or the OpenBenchmarking.org ID or saved local file name. Multiple arguments can be supplied to run additional tests at the same time and save the results in a suite-like fashion. Unlike the normal run option, the default-run will not prompt the user to select from the available test options but will instead use the default options as automatically set by pts-core or the test profile. Use batch-run to automatically test all of the available options. .TP .B internal-run [Test | Suite | OpenBenchmarking.org ID | Test Result] ... This option and its arguments pre-set the Phoronix Test Suite batch run mode with sane values for carrying out benchmarks in a semi-automated manner and without uploading any of the result data to the public OpenBenchmarking.org. .TP .SH OPENBENCHMARKING.ORG .B clone-result [OpenBenchmarking ID] ... This option will download a local copy of a file that was saved to OpenBenchmarking.org, as long as a valid public ID is supplied. More than one ID can be specified and the results will then be merged. .TP .B list-recommended-tests This option will list recommended test profiles for benchmarking sorted by hardware sub-system. The recommended tests are determined via querying OpenBenchmarking.org and determining the most popular tests for a given environment based upon the number of times a test profile has been downloaded, the number of test results available on OpenBenchmarking.org for a given test profile, the age of the test profile, and other weighted factors. .TP .B openbenchmarking-changes This option will list recent changes to test profiles of enabled OpenBenchmarking.org repositories. .TP .B openbenchmarking-launcher This option is called automatically with the .openbenchmarking MIME file extension support for launching OpenBenchmarking.org operations. .TP .B openbenchmarking-login This option is used for controlling your Phoronix Test Suite client options for OpenBechmarking.org and syncing the client to your account. .TP .B openbenchmarking-refresh This option is used for refreshing the stored OpenBenchmarking.org repostory information and other data. The Phoronix Test Suite will automatically refresh this data every three days or when other thresholds are exceeded, but this command can be used to manually refresh/updates the data. .TP .B openbenchmarking-repositories This option will list the OpenBenchmarking.org repositories currently linked to this Phoronix Test Suite client instance. .TP .B upload-result [Test Result] This option is used for uploading a test result to OpenBenchmarking.org. .TP .B upload-test-profile This option can be used for uploading a test profile to your account on OpenBenchmarking.org. By uploading your test profile to OpenBenchmarking.org, others are then able to browse and access this test suite for easy distribution in a seamless manner by other Phoronix Test Suite clients. .TP .B upload-test-suite This option can be used for uploading a test suite to your account on OpenBenchmarking.org. By uploading your test suite to OpenBenchmarking.org, others are then able to browse and access this test suite for easy distribution. .TP .SH SYSTEM .B detailed-system-info Display detailed information about the installed system hardware and software information as detected by the Phoronix Test Suite Phodevi Library. .TP .B diagnostics This option will print information that is useful to developers when debugging problems with the Phoronix Test Suite and/or test profiles and test suites. .TP .B interactive A simple text-driven interactive interface to the Phoronix Test Suite. .TP .B system-info Display the installed system hardware and software information as detected by the Phoronix Test Suite Phodevi Library. .TP .B system-sensors Display the installed system hardware and software sensors in real-time as detected by the Phoronix Test Suite Phodevi Library. .TP .SH INFORMATION .B info [Test | Suite | OpenBenchmarking.org ID | Test Result] This option will show details about the supplied test, suite, virtual suite, or result file. .TP .B list-available-suites This option will list all test suites that are available from the enabled OpenBenchmarking.org repositories. .TP .B list-available-tests This option will list all test profiles that are available from the enabled OpenBenchmarking.org repositories. .TP .B list-available-virtual-suites This option will list all available virtual test suites that can be dynamically created based upon the available tests from enabled OpenBenchmarking.org repositories. .TP .B list-installed-dependencies This option will list all of the packages / external test dependencies that are already installed on the system that the Phoronix Test Suite may potentially depend upon by test profiles. .TP .B list-installed-suites This option will list all suites that are currently installed on the system. .TP .B list-installed-tests This option will list all test profiles that are currently installed on the system. .TP .B list-missing-dependencies This option will list all of the packages / external test dependencies that are missing from the system that the Phoronix Test Suite may potentially need by select test profiles. .TP .B list-possible-dependencies This option will list all of the packages / external test dependencies that are are potentially used by the Phoronix Test Suite. .TP .B list-saved-results This option will list all of the saved test results found on the system. .TP .B list-test-usage This option will list various details about installed tests and their usage. .TP .B list-unsupported-tests This option will list all available test profiles that are available from the enabled OpenBenchmarking.org repositories but are NOT SUPPORTED on the given hardware/software platform. This is mainly a debugging option for those looking for test profiles to potentially port to new platforms, etc. .TP .SH ASSET CREATION .B debug-install [Test | Suite | OpenBenchmarking.org ID | Test Result] ... This option is intended for use by test profile writers and is identical to the install option but will yield more information during the run process that can be used to debug issues with a test profile installer or to verify the test profile is functioning correctly. .TP .B debug-run [Test | Suite | OpenBenchmarking.org ID | Test Result] ... This option is intended for use by test profile writers and is identical to the run option but will yield more information during the run process that can be used to debug issues with a test profile or to verify the test profile is functioning correctly. .TP .B debug-test-download-links [Test | Suite] This option will check all download links within the specified test profile(s) to ensure there are no broken URLs. .TP .B download-test-files [Test | Suite] ... This will download the selected test file(s) to the Phoronix Test Suite download cache but will not install the tests. .TP .B force-install [Test | Suite | OpenBenchmarking.org ID | Test Result] ... This option will force the installation (or re-installation) of a test or suite. The arguments and process is similar to the install option but even if the test is installed, the entire installation process will automatically be executed. This option is generally used when debugging a test installation problem. .TP .B result-file-to-suite [Test Result] This option will guide the user through the process of generating their own test suite, which they can then run, that is based upon an existing test results file. .TP .B validate-result-file This option can be used for validating a Phoronix Test Suite result file as being compliant against the OpenBenchmarking.org specification. .TP .B validate-test-profile This option can be used for validating a Phoronix Test Suite test profile as being compliant against the OpenBenchmarking.org specification. .TP .B validate-test-suite This option can be used for validating a Phoronix Test Suite test suite as being compliant against the OpenBenchmarking.org specification. .TP .SH RESULT MANAGEMENT .B copy-run-in-result-file [Test Result] This option is used if you wish to change an existing test run within a saved results file. .TP .B extract-from-result-file [Test Result] This option will extract a single set of test results from a saved results file that contains multiple test results that have been merged. The user is the prompted to specify a new result file name and select which result identifier to extract. .TP .B merge-results [Test Result] ... This option will manually merge multiple sets of test results generated by the Phoronix Test Suite. .TP .B refresh-graphs [Test Result] This option will re-render and save all result graphs within a saved file. This option can be used when making modifications to the graphing code or its color/option configuration file and testing the changes. .TP .B remove-from-result-file [Test Result] This option is used if there is a set of test results you wish to remove/delete from a saved results file. The user must specify a saved results file and then they will be prompted to select the results identifier associated with the results they wish to remove. .TP .B remove-result [Test Result] This option will permanently remove the saved file set that is set as the first argument. .TP .B rename-identifier-in-result-file [Test Result] This option is used if you wish to change the name of the identifier in a test results file that is shown in the Phoronix Test Suite Results Viewer and the contained graphs. .TP .B reorder-result-file [Test Result] This option is used if you wish to change the order in which test results are shown in the Phoronix Test Suite Results Viewer and the contained graphs. The user must specify a saved results file and then they will be prompted to select the results identifiers one at a time in the order they would like them to be displayed from left to right. .TP .B result-file-to-csv [Test Result] This option will read a saved test results file and output the system hardware and software information along with the results to a CSV output. The CSV (Comma Separated Values) output can then be loaded into a spreadsheet for easy viewing. .TP .B result-file-to-pdf [Test Result] This option will read a saved test results file and output the system hardware and software information along with the results to a PDF file. .TP .B result-file-to-text [Test Result] This option will read a saved test results file and output the system hardware and software information to the terminal. The test results are also outputted. .TP .B show-result [Test Result] Open up the test results in the Phoronix Test Suite Result Viewer or on OpenBenchmarking.org. .TP .SH RESULT ANALYTICS .B analyze-all-runs [Test Result] This option will generate a candlestick graph showing the distribution of results from all trial runs. The candlestick graph is similar to the Japanese candlestick charts used by the financial industry, except instead of representing stock data it is numerical result data from all trial runs.\n\nThe tip of the upper-wick represents the highest value of the test runs with the tip of the lower-wick representing the lowest value of all test runs. The upper-edge of the candle body represents the first or last run value and the lower-edge represents the first or last run value. Lastly, if the last run value is less than the first run value, the candle body is the same color as the graph background, otherwise the last run value is greater. .TP .B analyze-batch [Test Result] This option will analyze a batch results file and plot out the performance impact from the different options onto a line graph (i.e. to see the impact that changing the video resolution has on the system's performance). .TP .B analyze-image-delta [Test Result] This option will analyze a test result file if it contains any test results that produced an image quality comparison (IQC) and will render image deltas illustrating the difference between images from two test results. .TP .SH OTHER .B build-suite This option will guide the user through the process of generating their own test suite, which they can then run. Optionally, passed as arguments can be the test(s) or suite(s) to add to the suite to be created, instead of being prompted through the process. .TP .B debug-self-test This option is used during the development of the Phoronix Test Suite software for testing of internal interfaces, commands, and other common code-paths. The produced numbers should only be comparable for the same version of the Phoronix Test Suite, on the same hardware/software system, conducted on the same day of testing. This isn't intended as any scientific benchmark but simply to stress common PHP code-paths and looking for hot areas to optimize, etc. .TP .B help This option will display the list of available Phoronix Test Suite commands. .TP .B network-setup This option allows the user to configure how the Phoronix Test Suite connects to OpenBenchmarking.org and other web-services. Connecting through an HTTP proxy can be configured through this option. .TP .B rebuild-composite-xml [Test Result] This option can be used to rebuild your composite XML file in the event that the main result file was corrupted and the test-X.xml files are still present in the result file directory. .TP .B user-config-reset This option can be used for resetting the Phoronix Test Suite user configuration file to its default state. .TP .B user-config-set This option can be used for setting an XML value in the Phoronix Test Suite user configuration file. .TP .B version This option will display the Phoronix Test Suite client version. .TP .SH MODULES .B r p .TP .B list-modules This option will list all of the available Phoronix Test Suite modules on this system. .TP .B module-info [Phoronix Test Suite Module] This option will show detailed information on a Phoronix Test Suite module such as the version, developer, and a description of its purpose. .TP .B module-setup [Phoronix Test Suite Module] This option will allow you to configure all available end-user options for a Phoronix Test Suite module. These options are then stored within the user's configuration file. Not all modules may have options that can be configured by the end-user. .TP .SH SEE ALSO .B Websites: .br http://www.phoronix-test-suite.com/ .br http://commercial.phoronix-test-suite.com/ .br http://www.openbenchmarking.org/ .br http://www.phoronix.com/ .br http://www.phoronix.com/forums/ .SH AUTHORS Copyright 2008 - 2013 by Phoronix Media, Michael Larabel. .TP phoronix-test-suite/documentation/includes/pts-documentation.png0000644000175000017500000000601311050576041025457 0ustar michaelmichael‰PNG  IHDR‡FæS‡sBIT|dˆ pHYs**DdµTtEXtSoftwarewww.inkscape.org›î< ˆIDATxœí{´UÇ?÷r/\T ‘K.êRâ!*¦­Ò4MSi+4MÓ\Vf¾2SSSW–‰HK[¥&†h >V¢"æ“R$/ Š„(/ßþøíã™{93{ι3gÎÕù¬5ëž™ýúÍÌoöë÷ÛûÖI¢ð0&$l%0 Š²|jhÈZ€˜tº…„5USOõY S»äÊ‘JgiVr&L8JÒaáuuu'Ožü@eåÊÑÉ´pHDøÃI••7+9¡äÊ‘J®9¡äÊ‘J®9¡äÊ‘J®9¡äÊ‘J®9¡$1CÚôú=eÀÌ”Þ)üÊ  Ø»×>˜µ8-®ZSÌßK%ÊÑø"ppæKQW"Þà_ÀýÀTà• e¬öζ¬R™7Љ”£/p𠬆ðÑØË?`_ÃÀGå™!}€‰ÀÑY ’qú½€«€gO1J1¸ ø'p¥k›Zbð,ŸRÅ¿rŒæ[$Tæ ànà!`ë„òLšGY ’%QÊq20 Ø1¥²¿ÌvM)ÿJéL¶ËZ¬ SŽ ß“¾æPଠ¯¾ ì–µµ@)å8¸²Š2l‹}©ýªXf[?ÎZˆZ¡ýheð;âw['¹ØÜÆjì%ļ•vŽ™Ï`pðaÌ4z+3M[€{ÜïC€m<ñßÀF]/t \SÌ;Aåhî%^Çs%p ¦H+"â ¾‡õ_ºxò \‹UëåÐXfš ~Õ÷)àP`mÊë4•ã;ÄëÞ\¬‰÷àl(|0Âÿ à&àõy§Á Oø)tÅ5jÔ£’¶ ^?o޼Ѿ< ÊÑ ¸Ä·8 ¸5¾ˆ³k2îŽôÈs0®‚2’ oDØ›Ø\O§@ÒÀ!ÁëãäQ螇èv•)F€ã€ÙžxÇb³ªYÕôm¨š5BA9Ž÷Ä»¸>òÖc3ŽË=ñ|ò¤Å²ˆ°]€ÞÕ¤¨š!qÖßO°Ìåø‡ÊÇ$X^9´D„Õ7VKZ ¿í`ÖÞ&ÉD`iDø``÷˜y BWz¬ ä5ÃSÖIØèf’3'Ô, ÀÞž8÷¦Pî—ï¹qöÅì:>ÞÂzååòL¶(?ÃÝÑQ>Ä>7°9ž©À[ ä›õ„÷hVáï@VÊ}žð,fLW¿¬RYݱ~ÌÁÀ¯°Úy25dì«Ç|Âh6¥Tö«žð¨aeš\It“— ÀxÌAê¸ Êß _ÍÕ{ï(+ˆfekY Œ%æ\@ lMçÿ £ò?¦žh··÷S.?ʆ¬±VEÄëéɧžÁ:Ÿë|Säàë–Ÿ©÷yÌžÆ[!¿ÛÓ@:¾S±YÝÿ¤wê°>HfÖê,•c¨'<®rÄÉ«RžÅæ.Â:«Õ¦»+;²Ü¼å(Ox°S¸Ø÷PÌu ÖaöžŸcóbý´íˆ®ù|ôÄ̾ša<ð#RhâGŽ9ŽˆayVÊшÙP¢˜øý¸'îXÌp˜ÖÈ —÷l’Ú×c. ×®hMÀ˜Ñ2iFß ÌªY9[ÆKØäP70¯õ0š‰¸Éf6¯r…'ÞAUe3²PŽ^À¥ž8÷—¸6Ý“æg$7SZmn$zuàgª%Hj+GàD{´‹¢Û^?ÝlìèòöyœÕ"ï=ñ–‰5¸šÊш ÍBwÂs܉ͶçÌ-1Š/amóVeK—-MDÏ¿S-A‚TK9ú317»(6í‘v1~§ÞqØtŸ¸ÂÕ']ãùFk©¶rôÆl /Ĉ3°("|)6¬ôÑ ü˜‚Ywk¹©9[4Å,Ox*ø†²ýñÏGiÄæúcʰ7ñp.ñÖŒ\ ŒÆ†w>ƹc¦,K·i»{&¥‡§[‘¬“S{zŸÃï9ß ü9E9Bñ)ÇÂÿ•E’,Á”0Ž-cV Ïöˆ™ÿ6Øv¥xŸÒÊѸ,fþiò'>á}Ž(VcŠQŽ£ËÌ‹=Ê­ï“ÀGø‡ý©‘µr,Ä:Žó*HÛ‚5[O$*Qmq ¶¬#²TŽÇ°—ësú‰b%æI5)‰j‹;0{Nfd¡Ë€Ó±^z”ŸF\6߯:vsȯ¸3¸eJ5•ãÀ娒ËÛH~¿«YØ(æx*k¦jÀ×°dic‘¶UöMÌ&2 [ _UcSÜ1î‰ù{ôÁü#jX;“»föKó)ÇÊóÆÞ€5˰ÑG¹Û)$ÉblÑ÷-k=ØÜ-lõÝrÒs"¶/£|WÄÀ‹žp07‡mKE¨««+|¤K£òª“´‰pÌ)d·41'c²ÊæÔ0¹rä„’+GN(¹rä„w([Gq›† Ài»¡ÙcØ¢èZÙß¼—;•™.xŸ¥X‹Ý{šìŠy¥/ÜžÞ™nl„g;®XÄUŽn˜  ±èý€G°mª×`æùZÚøDà4`x™éºa®†a“wo»ó¹Øìn¥4=q¶Ne6 íì3ï'°tª;ïBG'%mR8÷HBR“;?Еô¡¤SÝy«¤ýÜïZ8ºJÚ*|æJº$!™Ž”´8"|KIë$í¸Ö½Œü·–Ôè~qïdëŽÈ\iŸãUà=Ú.ÈiÄ<Àç?¥m¦3Ž=í*ÜÉn4öµŽÀöC?É]Ò.;4£°9˜ØNËObkW LÑhµðmÝû¥c[-쀙æ`›è7r…ÍæSÜfb f:Øxøa‰<»âN"Þ |9p~m£~Cñ¹NÆžÿ}À¯q&`5ÌíÄñ…Qe5DZíÎ[%½,éBIKZ!é Ö[Ò"I%í)éRI«$íæÂ´VÒ IGK i{I-’&¹4»4{¸4‡Iú@ÒS’Nt– ïæÂÏ”ôÀWp¦¤å’ú»¼Kãë)UstqåÞ iwIÓ$ÝŸ/élI%à®u“t¾“a˜¤Ï†”w¹¤õ’®“Ô£]Ø|kj$]/iJà|±¤cÜï£Ýû#ipà½æ®'«¥vŒºÿr•c†¤×%m”tn £VIçÎgºEÒé’ÖHj„¿ éJµU޾ðñîZ×Àµç$]­¢r¬“ÔÜN¾*­HºKöR§Jº"ꡎRÊ1\öwq2Ÿ,éV/i©¤kTTÔÂ1VÒ’eŽ•)ÑB™"U¢CÝó6+»gÞׯKúV”,åޞÚŽçÙ|ífк‘â”ü^˜7x°#ö4m7Ã_KÛ½@örù u³1ŸË`š‚/H!^T3yfKX‚u¤+e8¶¶æ¡ÀµåXgv½Ë{2¶kó9;ˆq¹«úïÂî¹æ-×Q†c#¡Âf|­xþñA¹}ŽXû^΢Þl¸ CˆÞ„nQ‰4ƒ=i|\Ž£z½Q®‚ƒòžX_ª3Ð6{™åÎ/ÃÖÐ|¾‚2ÞÁ”¬ ëÃÚÀJÕ"xøE™›ik”ÜŒjL‚=‚YB ;ž=šÂ<·¥¸ýÑp`üK"ËuæÆaŽA·³¹òÅe&ö ƒžé=Üß&¬£×Š­Ð{âKlÁžCØ¿mkÆ1˜’<íÎbÿꣲFD—bÊÜ®{"p&mWÏõ ‚z¬j~-äHbo¬±ÿ wö€þŠùF>‘æ¬Z¾Á¥yû?q•(ÇNØr"6's§;¦RÙv‘ë1?‘0%yk°å Ó(n…=»_\¼é˜CO©…[}0EX¼ŒÕ:çS±ÜŒ=“w±m8o‹q56›üÖ]» û [\þ¯áÙ{ìÿR2!2h©oIEND®B`‚phoronix-test-suite/documentation/includes/pts-documentation.css0000644000175000017500000000232411050576041025464 0ustar michaelmichaelbody { text-align: center; margin: 0; padding: 0; font-family: arial, helvetica, sans-serif; font-size: 13px; background-color: #F9F9F9; color: #000; } a { color: #3B433A; } div#pts_doc_header { width: 100%; margin: 0; background-color: #000; } div#pts_doc_logo { width: 135px; height: 70px; padding: 3px; background: #000 url(pts-documentation.png) no-repeat; position: relative; left: 552px; } div.pts_doc_fixed { width: 700px; margin: 0 auto; } div.pts_doc_main { border: solid #737373; border-width: 0 1px; text-align: left; padding: 30px 20px; min-height: 670px; } div.pts_doc_notice { border: solid #737373; border-width: 0 1px; background-color: #222; text-align: left; overflow: hidden; padding: 4px 8px; color: #FFF; font-weight: bold; } div.pts_doc_bottom { background-color: #222; color: #FFF; text-align: left; padding: 3px 8px; font-size: 12px; overflow: hidden; } div.pts_doc_bottom a, div.pts_doc_notice a { color: #FFF; text-decoration: none; } h3 { text-indent: 30px; } h3 a { text-decoration: none; } div.pts_doc_bottom a:hover, div.pts_doc_notice a:hover, h3 a:hover { text-decoration: underline; } h1 { font-size: 22px; } h2 { font-size: 18px; } h3 { font-size: 15px; } phoronix-test-suite/documentation/old-docs/writing_your_first_test.html0000644000175000017500000002235511564542013027100 0ustar michaelmichael Phoronix Test Suite - A Quick Guide To Writing A Test Profile
Writing A Test Profile

Writing A Test Profile

Writing a test profile for the Phoronix Test Suite is a relatively quick and easy process for anyone familiar with common Linux commands and the basics of XML. To help you understand the design of the Phoronix Test Suite, this guide covers the steps needed to write a testing profile for a very simple application.

The first step in the profile writing process is to, well, have a piece of software you'd like to use with the Phoronix Test Suite. This software can be closed-source or open-source and be virtually anything as long as it is compatible with the Linux operating system.

For this guide, the piece of software being used for demonstration is just a simple C++ program that calculates Pi to 8,765,4321 digits using the Leibniz formula. Below is this sample piece of software intended just for demonstration purposes.

#include <iostream>
#include <math.h>

int main()
{
double pi = 0;

for(long int i = 1; i <= 87654321; i++)
pi += (double) pow(-1, i + 1) / (2 * i - 1);

pi *= 4;
std::cout << "Done Calculating Pi..." << endl;
return 0;
}

The first step in the actual profile writing process is to name it. If you're looking to ultimately push this profile to be included in the Phoronix Test Suite, its name must be all lower case and consist of just alpha-numeric characters, but can contain dashes (-). A more advanced test profile capability is operating system prefixes, and if using those there is an underscore separating the prefix from the normal profile name. For this sample profile, we're calling it sample-program and the file-name would be sample-program.xml. Our (very basic) profile is showcased below.

<PhoronixTestSuite>
     <TestProfile>
          <Version>1.1.0</Version>
          <TestType>Processor</TestType>
          <SoftwareType>Utility</SoftwareType>
          <License>FREE</License>
          <Status>PRIVATE</Status>
          <Maintainer>Phoronix Media</Maintainer>
     </TestProfile>
     <TestInformation>
          <Title>Sample Pi Program</Title>
          <TimesToRun>3</TimesToRun>
          <ResultScale>Seconds</ResultScale>
          <Proportion>LIB</Proportion>
          <Description>A simple C++ program that calculates Pi to 8,765,4321 digits using the Leibniz formula. This test can be used for showcasing how to write a basic test profile.</Description>
          <ExternalDependencies>build-utilities</ExternalDependencies>
     </TestInformation>
</PhoronixTestSuite>

This XML profile is what interfaces with the Phoronix Test Suite and provides all the needed information about the test as well as other attributes. For a complete listing of all the supported profile options, look at the specification files in the documentation folder. In the case of sample-program, it lets the Phoronix Test Suite know that it's composed of free software, is designed to test the processor, is intended for private use only, and this profile is maintained by Phoronix Media. In addition, it tells the Phoronix Test Suite to execute this program three times and as no result quantifier is set, the average of the three runs will be taken. This profile also tells the Phoronix Test Suite that the generic build-utilities package is needed, which will attempt to ensure that GCC and the standard development utilities/libraries are installed on your Linux distribution. This is needed as the C++ source-code will need to be built from source.

The next step is to write the install.sh file, which once called by the Phoronix Test Suite is intended to install the test locally for benchmarking purposes. The install.sh file is technically optional, but is generally used by all tests. Note: The first argument supplied to the install script is the directory that the test needs to be installed to. The install.sh file (in our instance) is to be placed inside pts/test-resources/sample-program. Below is the install.sh for the sample-program.

#!/bin/sh

tar -xjf sample-pi-program-1.tar.bz2
g++ sample-pi-program.cpp -o sample-pi-program
echo "#!/bin/sh
\$TIMER_START
./sample-pi-program 2>&1
\$TIMER_STOP
" > sample-program
chmod +x sample-program

Phoronix Test Suite 1.4 and later provides an integrated multi-platform micro-timer framework that provides the $TIMER_START and $TIMER_STOP functionality.

This install file builds the code with GCC, and then creates a small script that is run by the Phoronix Test Suite, which times how long it takes to run the software. Where does the source-code come into play? Well, it needs to be downloaded now from a web server. The Phoronix Test Suite has built-in support for managing downloads from multiple servers in a random over, fall-back support if one mirror is done, and verification of MD5 check-sums. Below is the downloads.xml file for sample-program that covers all of this.

<PhoronixTestSuite>
     <Downloads>
          <Package>
               <URL>http://www.phoronix-test-suite.com/benchmark-files/sample-pi-program.cpp</URL>
               <MD5>e90fb790df8d1544696a1439c9b5bd8d</MD5>
          </Package>
     </Downloads>
</PhoronixTestSuite>

The final step in the profile writing process is to write a parser to strip all information but the reported result from the standard output. The standard output is submitted to parse-results.sh or parse-results.php as the first argument in quotes or using $LOG_FILE if the test profile writes to that variable's location.

If the test profile uses the integrated micro-timer framework with $TIMER_START and $TIMER_STOP but no parse-results file is provided, the Phoronix Test Suite will automatically use the difference between $TIMER_START and $TIMER_STOP and use that as the test result. This is the time (in seconds) that elapsed between starting and stopping the timer.

After that, with all the files in their correct locations, just run: phoronix-test-suite benchmark sample-program. The Phoronix Test Suite should now handle the rest by installing the test, running the test, and recording the results (if you so choose). There is no additional work that needs to be done for the results to be recorded in the PTS Results Viewer or even reporting the results to OpenBenchmarking.org.

For more information, visit Phoronix-Test-Suite.com and read the included documentation. It should also be of great help to just look at the existing test profiles, which can be found inside the phoronix-test-suite/pts/ folder with the test-resources and test-profiles sub-directories.

phoronix-test-suite/documentation/old-docs/writing_your_first_module.html0000644000175000017500000001073711564542013027407 0ustar michaelmichael Phoronix Test Suite - Module Writing
Module Writing

Phoronix Test Suite Modules

Writing a module for the Phoronix Test Suite allows new functionality to be added without having to extensively learn how pts-core functions. The module framework for the Phoronix Test Suite allows modules to be written as a PHP object. Example PTS modules could include a module to shutdown the screensaver when the Phoronix Test Suite starts up and re-enabling it when the test is over, using sendmail to forward the results to an e-mail address when testing is completed, or writing the current test status to a LCDproc-enabled VFD display.

Modules are stored in pts-core/modules/. Loading a module is done by either setting the PTS_MODULES environmental variable with the name of the module (excluding the .php file extension) or by associating a module with a separate environmental variable. The default list of modules to be loaded is stored in ~/.phoronix-test-suite/user-config.xml.

Note: To run through all of the function calls for a module without needing to run a test, run phoronix-test-suite test-module MODULE_NAME. Additionally, running phoronix-test-suite debug-module MODULE_NAME will yield additional debugging details while executing the same process.

Module

To see all of the functions supported for modules written in PHP, look at pts-core/modules/dummy_module.php and additionally the other .php modules that ship with the Phoronix Test Suite. Additionally, there are several functions written specifically for Phoronix Test Suite modules that make it easier to save files, read files, and provided multi-threading support for modules. The pts_timed_function() makes it possible (and very easy) to thread functions within a module so that at a set interval the defined functions will be called. For example, this support is used heavily within the system_monitor module to poll sensors every X seconds even while there are tests running. These functions can be found within pts-core/objects/pts_module.php.

Below is a sample module that times how long it takes to run the Phoronix Test Suite. It would be saved as pts-core/modules/time_me.php.

<?php
class time_me extends pts_module_interface
{
    const module_name = "Time Me!";
    const module_version = "1.0.0";
    const module_description = "This is a module that times how long the Phoronix Test Suite runs.";
    const module_author = "Phoronix Media";

    static $start_time = NULL;
    static $end_time = NULL;

    public static function __startup()
    {
        self::$start_time = time();
    }
    public static function __shutdown()
    {
        self::$end_time = time();

        $time_elapsed = self::$end_time - self::$start_time;

        echo "\nThe Phoronix Test Suite Ran For " . $time_elapsed . " Seconds.\n";
    }
}
?>

Then by running PTS_MODULES=time_me phoronix-test-suite benchmark video-extensions, at the end of the test it would print a string similar to: "The Phoronix Test Suite Ran For 52 Seconds."

phoronix-test-suite/documentation/old-docs/test-profile-downloads.xml0000644000175000017500000000465511564542013026335 0ustar michaelmichael P_DOWNLOADS_PACKAGE_URL PhoronixTestSuite/Downloads/Package/URL The URL(s) to download the package from. If multiple URLs are supplied (delimited by a comma), the Phoronix Test Suite will randomly choose one URL but will fallback to other URLs if one fails either due to the file missing, the MD5 changed, or server inaccessability. YES P_DOWNLOADS_PACKAGE_MD5 PhoronixTestSuite/Downloads/Package/MD5 The MD5 check-sum for the file to be downloaded. This is to ensure file integrity. If no string is supplied, no MD5 check will be performed. RECOMMENDED P_DOWNLOADS_PACKAGE_FILENAME PhoronixTestSuite/Downloads/Package/FileName If this tag is set, once the file is downloaded it will be renamed to this value. If this tag is not set, the remote file-name will be used. NO P_DOWNLOADS_PACKAGE_FILESIZE PhoronixTestSuite/Downloads/Package/FileSize The size of the file to be downloaded should be the value of this tag. The FileSize should be an integer that is the number of bytes that makes up the file. This tag is used so that the Phoronix Test Suite can determine the total size of files that need to be downloaded for a given operation. RECOMMENDED P_DOWNLOADS_PACKAGE_PLATFORMSPECIFIC PhoronixTestSuite/Downloads/Package/PlatformSpecific If this package is just needed on select operating systems / platforms, list them inside this tag and multiple platforms can be delimited by a comma. NO P_DOWNLOADS_PACKAGE_ARCHSPECIFIC PhoronixTestSuite/Downloads/Package/ArchitectureSpecific If this package is just needed on select system/processor architectures, list them inside this tag and multiple architectures can be delimited by a comma. NO phoronix-test-suite/documentation/old-docs/results-parser.xml0000644000175000017500000001613111564542013024713 0ustar michaelmichael P_RESULTS_PARSER_MATCH_TO_TEST_ARGUMENTS PhoronixTestSuite/ResultsParser/MatchToTestArguments If there are multiple ResulsParser sections within the XML file and this tag is set, the Phoronix Test Suite will see if this string appears within the PTS_TEST_ARGUMENTS in determining if this is the ResultsParser section to use for parsing the results. P_RESULTS_PARSER_TEMPLATE PhoronixTestSuite/ResultsParser/OutputTemplate The section of the test output to look for the result(s) within. P_RESULTS_PARSER_RESULT_KEY PhoronixTestSuite/ResultsParser/ResultKey The key to look for when parsing the OutputTemplate to find where the result should be stored. If this tag is not implemented, the default key will be used. P_RESULTS_PARSER_LINE_HINT PhoronixTestSuite/ResultsParser/LineHint A unique string to search the test result output for to indicate this is the line that contains the result value. P_RESULTS_PARSER_LINE_BEFORE_HINT PhoronixTestSuite/ResultsParser/LineBeforeHint The LineBeforeHint tag is similar to LineHint but is used to indicate the line before where the test results appear, in the event the LineHint tag cannot be used reliably. P_RESULTS_PARSER_LINE_AFTER_HINT PhoronixTestSuite/ResultsParser/LineAfterHint The LineAfterHint tag is similar to LineBeforeHint but is used to indicate the line after where the test results appear, in the event the LineHint or LineBeforeHint tags cannot be used reliably. P_RESULTS_PARSER_RESULT_BEFORE_STRING PhoronixTestSuite/ResultsParser/ResultBeforeString The ResultBeforeString tag is optional and can be used if there is a consistient string following the reporting of the result, in the event the result's location is not static within the line string. P_RESULTS_PARSER_STRIP_FROM_RESULT PhoronixTestSuite/ResultsParser/StripFromResult Any string that should be searched for and removed from the result value anywhere within the value string. P_RESULTS_PARSER_STRIP_RESULT_POSTFIX PhoronixTestSuite/ResultsParser/StripResultPostfix This is similar to the StripFromResult tag but will only look at the end of the value string for this string to be removed. (I.e. if a unit such as 'ms' or 'FPS' is appended to the result by the test without a space.) P_RESULTS_PARSER_MULTI_MATCH PhoronixTestSuite/ResultsParser/MultiMatch If the result value should be found multiple times within the result file and then some mathematical operation carried out, it should be set using this tag. Setting the value to AVERAGE will find all matches and then calculate the average value based upon matches. While not required, setting the value to NONE will use the default code-path of only looking for one result value. P_RESULTS_PARSER_DIVIDE_BY PhoronixTestSuite/ResultsParser/DivideResultBy If the result value should be divided by some constant (to convert the result to a different unit), the value should be supplied in this tag. P_RESULTS_PARSER_MULTIPLY_BY PhoronixTestSuite/ResultsParser/MultiplyResultBy If the result value should be multiplied by some constant (to convert the result to a different unit), the value should be supplied in this tag. P_IMAGE_PARSER_MATCH_TO_TEST_ARGUMENTS PhoronixTestSuite/ImageParser/MatchToTestArguments If there are multiple ResulsParser sections within the XML file and this tag is set, the Phoronix Test Suite will see if this string appears within the PTS_TEST_ARGUMENTS in determining if this is the ResultsParser section to use for parsing the results. P_IMAGE_PARSER_SOURCE_IMAGE PhoronixTestSuite/ImageParser/SourceImage If the test profile is for an image quality comparison, the ImageFile tag should contain the file/path of the source file. P_IMAGE_PARSER_IMAGE_X PhoronixTestSuite/ImageParser/ImageX If the test profile is for an image quality comparison, the ImageX should be the X coordinate of where to begin cropping the source file. P_IMAGE_PARSER_IMAGE_Y PhoronixTestSuite/ImageParser/ImageY If the test profile is for an image quality comparison, the ImageX should be the Y coordinate of where to begin cropping the source file. P_IMAGE_PARSER_IMAGE_WIDTH PhoronixTestSuite/ImageParser/ImageWidth If the test profile is for an image quality comparison, the ImageWidth should be the produced image width. P_IMAGE_PARSER_IMAGE_HEIGHT PhoronixTestSuite/ImageParser/ImageHeight If the test profile is for an image quality comparison, the ImageHeight should be the produced image height. P_MONITOR_PARSER_SENSOR PhoronixTestSuite/SystemMonitor/Sensor If the test profile is to monitor any system sensors during the testing process, the name of the sensor (via the Phodevi name; i.e. cpu.usage) should be supplied. While not a Phodevi sensor, if passing sys.time as the sensor value, the time it takes to execute the test will be recorded. P_MONITOR_PARSER_FREQUENCY PhoronixTestSuite/SystemMonitor/PollingFrequency If the test profile is to monitor any system sensors during the testing process, how often the matched sensor is to be polled (in seconds) should be supplied. Floating values are supported. P_MONITOR_PARSER_REPORT PhoronixTestSuite/SystemMonitor/Report If the test profile is to monitor any system sensors during the testing process, this tag provides how the monitored results should be reported. Supported values include MAX, MIN, AVG, and ALL. phoronix-test-suite/documentation/stubs/01_install.html0000644000175000017500000002657412144771510023503 0ustar michaelmichael Installation Instructions

Setup Overview

The Phoronix Test Suite supports Linux, Apple Mac OS X, Microsoft Windows, Solaris, Hurd, BSD, and other operating system environments. The only Linux distribution-specific code deals with the external dependencies support feature that are set by individual test profiles. If you are not running one of the supported Linux distributions, Solaris, BSD, or Mac OS X, you may need to install a package manually (as instructed by the Phoronix Test Suite) in order for a test to run. An example of an external dependency would be GCC and the OpenGL Utility Toolkit being needed for test profiles that build an OpenGL benchmark from source-code.

Among the distributions where the Phoronix Test Suite has been officially tested include Ubuntu, Fedora, Mandriva / Mageia, Gentoo, PCLinuxOS, Arch Linux, Pardus, OpenSuSE, Optware, webOS, Zenwalk, CentOS, Red Hat Enterprise Linux, Oracle Linux, Scientific Linux, Debian, Mint, MEPIS, and Amazon Linux EC2.

Among the tested BSD distributions are FreeBSD, PC-BSD, NetBSD, OpenBSD, Debian GNU/kFreeBSD, and DragonflyBSD. Tested Solaris distributions include OpenSolaris, Solaris Express 11, Oracle Solaris 11, OpenIndiana, Illumos, and Nexenta.

Dependencies

The only required dependency for the Phoronix Test Suite is PHP 5.2 or newer. On Linux distributions, the needed package is commonly called php5-cli or php-cli or php. It is important to note that only PHP for the command-line is needed and not a web server (Apache) or other packages commonly associated with PHP and its usage by web-sites. The PHP5 version required is PHP 5.2+ and can also be found at www.php.net.

As part of the PHP requirement, the following PHP extensions are required and/or highly recommended in order to take advantage of the Phoronix Test Suite capabilities:

  • PHP DOM is needed for XML operations and must be installed for the Phoronix Test Suite to function.
  • PHP ZIP is needed for file compression and decompression and specifically dealing with test profiles and suites obtained via OpenBenchmarking.org or when uploading such tests and suites.
  • PHP OpenSSL is used for enabling HTTPS communication with Phoronix Test Suite / OpenBenchmarking.org servers.
  • PHP GD is highly recommended for rendering of test data to JPEG and PNG image formats and is selectively used in other image operations.
  • PHP Zlib is highly recommended for greater data compression when dealing with remote OpenBenchmarking.org assets.
  • PHP PCNTL is used for multi-threaded system sensor monitoring support during the testing process and other threaded tasks by the Phoronix Test Suite module framework.
  • PHP POSIX is used for reliably obtaining more system information in an efficient manner.
  • PHP CURL is supported as an alternative networking library for improved network performance in downloading test files and other operations.
  • PHP FPDF is used to generate PDF reports of test data.

Without all of these extensions, some capabilities of the Phoronix Test Suite will not be available. Many of these packages are enabled by default and do not require any additional installation steps on most Linux distributions, otherwise they are often found in the package vendor's repository.

Notes

General

You may need to modify the php.ini file on your system in order to support uploading results to OpenBenchmarking.org or logging into your OpenBenchmarking.org account. The allow_url_fopen, file_uploads, and allow_url_include options must be set to true in the PHP configuration. See additional information in this Phoronix Forums support thread.

Major updates to the Phoronix Test Suite are released on a quarterly basis. The latest stable and development versions of the Phoronix Test Suite are available at Phoronix-Test-Suite.com. The Git repository where the latest Phoronix Test Suite code is provided is hosted at Phorogit.com and can be cloned/pulled from the http://www.phorogit.com/repo/phoronix-test-suite.git repository. The latest upstream development code is housed in the master tree while older Phoronix Test Suite releases are available in their respective Git branches based upon the release's code-name.

If building the PHP package from upstream sources, it should just be a matter of running ./configure with the --enable-zip flag (all other requirements should be apart of the stock PHP configuration) to satisfy the PHP needs of the Phoronix Test Suite.

File Structure

If manually changing the location of the phoronix-test-suite launcher file, the PTS_USER_PATH environment variable must be adjusted inside the file to reflect the absolute location that leads to the root directory of the pts and pts-core folders. The pts-core directory contains the "engine" of the Phoronix Test Suite.

Running Locally

The Phoronix Test Suite can be simply extracted from the downloaded .tar.gz or .zip file or it can also be installed system-wide. If you just wish to run the Phoronix Test Suite without installing it, open a terminal and run ./phoronix-test-suite <options> from the same directory.

Generic Installation

Running install-sh from the root directory of the Phoronix Test Suite will install the software for system-wide access. By default the phoronix-test-suite executable is in /usr/bin/, the Phoronix Test Suite files in /usr/share/phoronix-test-suite/, and the documentation in /usr/share/doc/phoronix-test-suite/. Root access is required. The default installation prefix is /usr/ but can be adjusted as the first argument (example: install-sh /home/user/ to install the Phoronix Test Suite in your home directory).

Debian/Ubuntu Installation

Debian/Ubuntu users are able to follow the Generic Installation instructions or can obtain a Debian Package from the Phoronix Test Suite web-site. The package contains the phoronix-test-suite executable in /usr/bin/, the Phoronix Test Suite files in /usr/share/phoronix-test-suite/, and the documentation in /usr/share/doc/phoronix-test-suite/.

A phoronix-test-suite package can also be found in the official Ubuntu universe repository beginning with the Ubuntu 9.04 (Jaunty) release, but it may be out of date compared to the latest upstream version.

Fedora / Red Hat Installation

The Phoronix Test Suite can be installed on Fedora, Red Hat Enterprise Linux, and CentOS systems using the generic installation method. Alternatively, a phoronix-test-suite package is available in recent versions of the Fedora repository and in the EPEL (Extra Packages for Enterprise Linux) repository for Red Hat Enterprise Linux. At this time, however, the Fedora-supplied package is vastly out of date.

Gentoo Installation

Gentoo ebuild's for the Phoronix Test Suite have been created by users and can be currently found in the Gentoo BugZilla.

Mandriva Installation

Phoronix Test Suite packages are available through Mandriva Cooker starting with the Mandriva Linux 2009 release.

OpenSolaris Installation

The Phoronix Test Suite core (pts-core) is supported on Solaris and OpenSolaris platforms, but some features may not fully function. Additionally, the PTS External Dependencies feature is supported on OpenSolaris using IPS (the Image Packaging System). However, not all test profiles are supported on Solaris / OpenSolaris, and it may be in violation of your end-user agreement to perform such benchmarks on the Sun Solaris operating system. Using the OpenSolaris Image Packaging System, installing SUNWphp524 will provide PHP, PHP GD, and related dependencies. The Phoronix Test Suite has also been tested on Oracle Solaris 11 Express, OpenIndiana, StormOS, and Nexenta Core Platform.

BSD Installation

The Phoronix Test Suite also supports *BSD operating systems. However, like the Solaris support, not all test profiles are compatible with BSD operating systems, but pts-core has been tested against FreeBSD 7.x/8.x/9.x, NetBSD, PC-BSD 7/8/9, DragonFlyBSD 3.0/3.2/3.4, and OpenBSD 4.4/4.6. The Phoronix Test Suite will also work with Debian GNU/kFreeBSD.

For DragonFlyBSD, it's a matter of just using pkg_radd with php5, php5-json, php5-dom, and php5-zip or pkgsrc. Under FreeBSD/PC-BSD, PHP can be obtained from the php5 and php5-extensions Ports collection.

Mac OS X Installation

The Phoronix Test Suite is fully supported on Apple's Mac OS X operating system as of Mac OS X 10.5 with improved support under Mac OS X 10.6. PHP ships with Mac OS X by default so it's simply a matter of downloading the Phoronix Test Suite package, extracting it, and running the executable. For tests that rely upon a compiler, Apple's XCode with GCC and LLVM can be utilized.

Windows Installation

The Phoronix Test Suite support on Windows is in development and will function just fine, but is not yet feature complete compared to the other operating systems support. At this time the Phoronix Test Suite client is dependent upon PHP being installed to C:\Program Files (x86)\PHP\php. The Phoronix Test Suite also uses CPU-Z for much of the hardware detection support on Windows and is dependent upon CPU-Z being installed to C:\Program Files\CPUID\CPU-Z\cpuz.exe if you wish to utilize this hardware reporting feature. In terms of the Microsoft Windows support, right now the Phoronix Test Suite is developed and solely tested against Microsoft Windows 7 x64 and Microsoft Windows 8 x64.

Facebook HipHop

The Phoronix Test Suite can use Facebook's HopHop HHVM virtual machine as an alternative to the de facto PHP implementation. The Phoronix Test Suite has been tested against HHVM 2.0. If HHVM is present on the system but not PHP, it will automatically be used by the Phoronix Test Suite. Alternatively, the PHP_BIN environment variable can be set to point to an alternative hhvm binary.

The Phoronix Test Suite also supports the older version of Facebook HipHop that serves as a PHP to C++ translator and compiler with GCC. This support though is primitive and not officially supported. To compile the Phoronix Test Suite using HipHop/GCC, run find . -name "*.php" > files.list && hphp --input-list=files.list -k 1 --log=3 --include-path="." --cluster-count=50 -v "AllDynamic=true" -v "AllVolatile=true" from the root phoronix-test-suite/ directory. It can then be executed in the form of /tmp/hphp_XXX/program -f pts-core/phoronix-test-suite.php system-info.

phoronix-test-suite/documentation/stubs/99_development_credits.html0000644000175000017500000000367212212733060026101 0ustar michaelmichael Development Credits

The Phoronix Test Suite is based upon the extensive testing and internal tools developed by Phoronix.com since 2004 along with support from leading tier-one computer hardware and software vendors. The principal architects of the Phoronix Test Suite are Michael Larabel and Matthew Tippett. The phoronix-test-suite, pts_Graph, bilde_renderer, Phodevi, tandem_Xml, and nye_Xml are some of the related open-source projects provided by Phoronix Media.

Below is a list of individuals and organizations that have contributed upstream patches, test profiles, and/or made other contributions to the Phoronix Test Suite that Phoronix Media would like to thank.

  • Achim Gottinger
  • Achim Lange
  • Andrew Schofield
  • Apaige
  • Ben Kero
  • Bryan Quigley
  • Chris Campbell
  • Daniel Díaz
  • Daniel Stodden / Citrix
  • Dean Hilkewich
  • ESET s.r.o.
  • Fatima Sheremetyeva
  • Fujitsu
  • Hans Ulrich Niedermann
  • Intel Open-Source Technology Center
  • Jeroen van Rijn
  • Johannes Obermayr
  • Juan Aguado
  • Jörg Schirottke
  • Kenney Phillis
  • Kim Bisgaard
  • Laminar Research
  • Marco Poletti
  • Matthew Tippett
  • Michael Larabel
  • Michael Opdenacker
  • Michael Ploujnikov
  • Michal Zatloukal
  • Nils Kneuper
  • NVIDIA Corporation
  • Pekka Panula
  • Peter Kraus
  • Rainer König
  • SOMA Networks, Inc.
  • Stefan Doesinger
  • Stepan Hrbek
  • Stéphane Teletchéa
  • Sun Microsystems
  • Tao Zhang
  • Thomas Klausner
  • Unigine Corp
  • Vadim Peretokin
  • Zachary Powers
phoronix-test-suite/documentation/stubs/40_configuration.html0000644000175000017500000002127512172340720024674 0ustar michaelmichael Configuration

User Files & Folders

~/.phoronix-test-suite/user-config.xml

This is a per-user configuration file. Among the information stored here is the test options, locations for storing files, and batch mode options. This file is formatted in XML.

~/.phoronix-test-suite/graph-config.json

This is a per-user configuration file for storing graph attributes. The adjustable options include HTML hex color codes for different areas of the graph, dimensions of the graph, and font sizes. This file is formatted in JSON.

~/.phoronix-test-suite/download-cache/

This directory contains test packages that have been downloaded for test profiles. For more information on the download cache.

~/.phoronix-test-suite/installed-tests/

This directory is where tests are installed by default. Each test has its own directory within a sub-directory of installed-tests/ based upon its OpenBenchmarking.org repository. In the test's folder is a pts-install.xml file used for managing the installation.

~/.phoronix-test-suite/test-results/

This directory is where tests results are saved by default. Each saved file has its own directory. In the saved directory is then a composite.xml file containing the useful results while in the test-X.xml files are back-ups of the results.

~/.phoronix-test-suite/modules-data/

This is the directory where any Phoronix Test Suite modules should save any files to, within a sub-directory of the module's name. The module configuration settings are also stored within this directory.

~/.phoronix-test-suite/test-profiles/

This is the directory where test profiles are stored.

~/.phoronix-test-suite/test-suites/

This is the directory where test suites are stored.

Environment Variables

TEST_RESULTS_NAME

When this variable is set, the value will be used as the name for automatically saving the test results.

TEST_RESULTS_IDENTIFIER

When this variable is set, the value will be used as the test identifier when automatically saving the test results.

TEST_RESULTS_DESCRIPTION

When this variable is set, the value will be used as the test results description when saving the test results.

PRESET_OPTIONS

For setting any test option(s) from an environment variable rather than being prompted for the options when running a test. Example: PRESET_OPTIONS="stream.run-type=Add" ./phoronix-test-suite benchmark stream

SKIP_TESTS

If there are any test(s) to exempt from the testing process, specify them in this variable. Multiple tests can be waived by delimiting each test identifier by a comma. A test hardware type (i.e. Graphics) can also be supplied for skipping a range of tests.

ONLY_TEST_TYPES

If you are running a set of benchmarks (namely a result file) but wish to skip some of the tests that don't belong to a certain test type group, you can set the hardware types to test via this environment variable. E.g. setting ONLY_TEST_TYPE=Graphics will skip all test profiles to run that are not of the graphics test group. Multiple types should be delimited by a comma.

PTS_MODULE_SETUP

This variable can be used to load Phoronix Test Suite module settings automatically when using the module-setup option. An example would be: PTS_MODULE_SETUP="phoromatic.remote_host=http://www.phoromatic.com/; phoromatic.remote_account=123456; phoromatic.remote_verifier=ABCD" phoronix-test-suite module-setup phoromatic.

PTS_MODULES

If there are any Phoronix Test Suite modules to additionally load, they can be specified here. Multiple modules can be supplied by delimiting them with a comma. The more appropriate way of loading Phoronix Test Suite modules for longer periods of time is by using the ~/.phoronix-test-suite/user-config.xml configuration.

NO_PHODEVI_CACHE

This is a debugging option to disable the Phodevi cache from being loaded of cached software/hardware information. Instead, all software/hardware will be polled from the Phodevi library without caching.

EXTERNAL_PHODEVI_CACHE

This option can be used for loading an external Phodevi cache. Such as loading the native hardware/software information from within a Windows Wine client from a native system host.

PTS_DISPLAY_MODE

If you wish to load a non-default display mode for a single instance, specify the mode in this variable.

TOTAL_LOOP_TIME

When running any test(s), if you would like the test(s) to continue running as a loop until a certain time has been reached, this variable can be used. The value should be the number of minutes to run the testing process before the loop is ended.

TOTAL_LOOP_COUNT

When running any test(s), if you would like the test(s) to continue running for a number of times, this variable can be used. The value should be the number of times to loop the testing process before ending.

FORCE_TIMES_TO_RUN

If you wish to override the number of times to run each test -- rather than the Phoronix Test Suite using the number of times specified in each test profile -- this variable can be used.

FORCE_MIN_TIMES_TO_RUN

This is similar to the FORCE_TIMES_TO_RUN option but will only be used if the test profile's run count is less than this defined value.

NO_FILE_HASH_CHECKS

To disable MD5/SHA256 check-sums from being checked when downloading test files, set this variable to 1. This variable used to be known as NO_MD5_CHECKS, which is still honored but was changed to NO_FILE_HASH_CHECKS to reflect other kind of file hash sum checks.

PTS_DOWNLOAD_CACHE

While non-standard Phoronix Test Suite download caches can be specified within the user-config.xml file, an additional directory to look for potential Phoronix Test Suite download files can be specified by this variable.

GRAPH_HIGHLIGHT

If this variable is set with a valid test identifer from a result file whether you are using the refresh-graphs command or any other related to the rendering of test results on a bar graph, the specified test identifier's result will be highlighted in a different color than the other rendered test results. Multiple identifiers can be specified when delimited by a comma.

VIDEO_MEMORY

If Phodevi fails to detect the system's video memory capacity or is incorrectly detected, the video memory capacity (in MB) can be specified by this variable.

OVERRIDE_VIDEO_MODES

If Phodevi fails to detect all of the system's monitor video modes or a separate set of modes would be preferred, the modes can be specified in this variable. Example: OVERRIDE_VIDEO_MODES=800x600,1024x768,1280x1024 phoronix-test-suite benchmark nexuiz.

SKIP_TEST_SUPPORT_CHECKS

If this environment variable is set, it will not honor the support checks made by individual test profiles. I.e. test profiles that would normally be considered un-supported on a given platform are attempted to install and run regardless.

SKIP_ALL_TEST_SUPPORT_CHECKS

If this environment variable is set, all tests will be permitted on the client for execution. SKIP_ALL_TEST_SUPPORT_CHECKS is more liberal than SKIP_TEST_SUPPORT_CHECKS in letting disk tests run on RAM-based file-systems, attempt to run 2D/3D tests on VESA display drivers, and other special cases.

DEFAULT_VIDEO_MODE

If Phodevi fails to detect the system's monitor standard / default resolution, the mode can be specified in this variable. Example: DEFAULT_VIDEO_MODE=1680x1050 phoronix-test-suite benchmark nexuiz.

SKIP_EXTERNAL_DEPENDENCIES

To skip the Phoronix Test Suite external dependency checking/installation when installing a test, set this environment variable to 1. If wishing to skip only certain external dependencies, set this variable's value to the name of the external dependencies (the generic dependency names used by the Phoronix Test Suite) to not install. Multiple dependencies to skip can be delimited by a comma.

phoronix-test-suite/documentation/stubs/00_overview.html0000644000175000017500000001120011747251434023664 0ustar michaelmichael Getting Started

Overview

The Phoronix Test Suite is the most comprehensive testing and benchmarking platform available for Linux, Solaris, Mac OS X, and BSD operating systems. The Phoronix Test Suite allows for carrying out tests in a fully automated manner from test installation to execution and reporting. All tests are meant to be easily reproducible, easy-to-use, and support fully automated execution. The Phoronix Test Suite is open-source under the GNU GPLv3 license and is developed by Phoronix Media in cooperation with partners. Version 1.0 of the Phoronix Test Suite was publicly released in 2008.

The Phoronix Test Suite client itself is a test framework for providing seamless execution of test profiles and test suites. There are more than 200 tests available by default, which are transparently available via OpenBenchmarking.org integration. Of these default test profiles there is a range of sub-systems that can be tested and a range of hardware from mobile devices to desktops and worksrtations/servers. New tests can be easily introduced via the Phoronix Test Suite's extensible test architecture, with test profiles consisting of XML files and shell scripts. Test profiles can produce a quantitative result or other qualitative/abstract results like image quality comparisons and pass/fail. Using Phoronix Test Suite modules, other data can also be automatically collected at run-time such as the system power consumption, disk usage, and other software/hardware sensors. Test suites contain references to test profiles to execute as part of a set or can also reference other test suites. Test suites are defined via an XML schema.

Running the Phoronix Test Suite for the first time can be as simple as issuing a command such as phoronix-test-suite benchmark c-ray, which would proceed to install a simple CPU test, execute the test, and report the results. Along with the results, the system's hardware/software information is collected in a detailed manner, relevant system logs, and other important system attributes such as compiler flags and system state. Users can optionally upload their results to OpenBenchmarking.org for sharing results with others, comparing results against other systems, and to carry out further analysis.

OpenBenchmarking.org

OpenBenchmarking.org is an open, collaborative testing platform that makes the Phoronix Test Suite an even more extensible platform for conducting automated tests with complete integration into Phoronix Test Suite test client. OpenBenchmarking.org serves as a repository for storing test profiles, test suites, and result data. Test profiles and suites are stored in the OpenBenchmarking.org cloud to allow for new/updated tests to be seamlessly obtained via the Phoronix Test Suite without needing to manually update the Phoronix Test Suite client. OpenBenchmarking.org also makes it easy to facilitate side-by-side comparisons with any other results stored in the OpenBenchmarking.org cloud. Any Phoronix Test Suite user is permitted to upload their test results, test profiles, and suites to OpenBenchmarking.org.

When finding a set of results on OpenBenchmarking.org (e.g. an example result file), it's as easy as running the Phoronix Test Suite with that OpenBenchmarking.org ID to perform an automated side-by-side comparison (e.g. phoronix-test-suite benchmark 1203160-BY-NVTEGRA3785).

Thanks to the wealth of test data (results, system logs, etc) from crowd-sourced benchmarking via the Phoronix Test Suite, a plethora of analytical features are also available from OpenBenchmarking.org.

Phoromatic

Phoromatic is a remote management system for the Phoronix Test Suite that allows the automatic scheduling of tests, remote installation of new tests, and the management of multiple test systems all through an intuitive, easy-to-use web interface. Tests can be scheduled to automatically run on a routine basis across multiple test systems. Phoromatic can also interface with revision control systems to offer support for issuing new tests on a context-basis, such as whenever a Git commit has been pushed or new daily image available. The test results are then available from this central, secure location.

Phoromatic is an add-on to the Phoronix Test Suite that's primarily intended for enterprise users when facilitating tests across a wide-spectrum of hardware within a test lab or when needing to carry out tests on a routine basis.

phoronix-test-suite/documentation/stubs/00_zmodule_options.html0000644000175000017500000000665312223157103025254 0ustar michaelmichaelModule Options

The following list is the modules included with the Phoronix Test Suite that are intended to extend the functionality of pts-core. Some of these options have commands that can be run directly in a similiar manner to the other Phoronix Test Suite user commands. Some modules are just meant to be loaded directly by adding the module name to the LoadModules tag in ~/.phoronix-test-suite/user-config.xml or via the PTS_MODULES environmental variable. A list of available modules is also available by running phoronix-test-suite list-modules.


Dummy Module

This is a simple module intended for developers to just demonstrate some of the module functions.

phoronix-test-suite dummy_module.dummy-command

OpenBenchmarking.org Ekofisk

The Ekofisk client is used for connecting to OpenBenchmarking.org to facilitate the automatic running of tests, generally across multiple test nodes in a routine manner.

phoronix-test-suite ekofisk.start

phoronix-test-suite ekofisk.user-system-return

Graphics Event Checker

This module checks a number of events prior to and and after running a test to make sure the graphics sub-system was not put in a sour or unintended state by the application. For instance, it makes sure syncing to vBlank is not forced through the driver and that a graphics test has not left the display in an unintended mode.

Graphics Override

This module allows you to override some graphics rendering settings for the ATI and NVIDIA drivers while running the Phoronix Test Suite.

This module utilizes the following environmental variables: FORCE_AA, FORCE_AF.

MATISK

My Automated Test Infrastructure Setup Kit

phoronix-test-suite matisk.run

phoronix-test-suite matisk.template

Phoromatic Client

The Phoromatic client is used for connecting to a Phoromatic server (Phoromatic.com or a locally run server) to facilitate the automatic running of tests, generally across multiple test nodes in a routine manner. For more details visit http://www.phoromatic.com/

phoronix-test-suite phoromatic.start

phoronix-test-suite phoromatic.user-system-return

phoronix-test-suite phoromatic.upload-results

phoronix-test-suite phoromatic.clone-results

phoronix-test-suite phoromatic.system-schedule

phoronix-test-suite phoromatic.system-schedule-today

phoronix-test-suite phoromatic.send-message

Result Notifier

A notification module.

System Monitor

This module contains sensor monitoring support.

This module utilizes the following environmental variables: MONITOR, PERFORMANCE_PER_WATT.

Timed Screenshot

This is a module that will take a screenshot of the system at a pre-defined interval. ImageMagick must be installed onto the system prior to using this module.

This module utilizes the following environmental variables: SCREENSHOT_INTERVAL.

Toggle Screensaver

This module toggles the system's screensaver while the Phoronix Test Suite is running. At this time, the GNOME and KDE screensavers are supported.

This module utilizes the following environmental variables: HALT_SCREENSAVER.

Update Checker

This module checks to see if the Phoronix Test Suite -- and its tests and suites -- are up to date.

phoronix-test-suite/documentation/stubs/02_external_dependencies.html0000644000175000017500000000306212223157103026343 0ustar michaelmichaelExternal Dependencies

The Phoronix Test Suite has a feature known as "External Dependencies" where the Phoronix Test Suite can attempt to automatically install some of the test-specific dependencies on supported distributions. If running on a distribution where there is currently no External Dependencies profile, the needed package name(s) are listed for manual installation.

Below are a list of the operating systems that currently have external dependencies support within the Phoronix Test Suite for the automatic installation of needed test files.


  • Amazon
  • Angstrom
  • Arch Linux
  • CentOS
  • ClearOS
  • ClearOS Core Server
  • Debian
  • DragonFlyBSD
  • Fedora
  • Fluxbuntu
  • FreeBSD
  • GNU KFreeBSD
  • Gentoo
  • Goobuntu
  • HP
  • Joli Cloud
  • Linaro
  • Linux Mint
  • MEPIS
  • Mac OS X
  • MacPorts
  • Mageia
  • Mandriva
  • MeeGo
  • Moblin
  • Mythbuntu
  • NetBSD
  • Nexenta Core
  • OLPC
  • OpenIndiana
  • OpenMandriva
  • OpenSolaris
  • OpenSuSE
  • Optware
  • Oracle Server
  • PCLinuxOS
  • PTS Desktop Live
  • PTS Linux Live
  • Palm
  • Pardus Linux
  • Red Hat Enterprise
  • Red Hat Enterprise Server
  • SUSE
  • SUSE Linux
  • Scientific
  • ScientificSL
  • Ubuntu
  • Zenwalk
  • gNewSense
  • phoronix-test-suite/documentation/stubs/readme-basics.txt0000644000175000017500000001071511747254422024103 0ustar michaelmichaelThe Phoronix Test Suite itself is an open-source framework for conducting automated tests along with reporting of test results, detection of installed system software/hardware, and other features. Modules for the Phoronix Test Suite also allow for integration with git-bisect and other revision control systems for per-commit regression testing, system sensor monitoring, and other extras. This framework is designed to be an extensible architecture so that new test profiles and suites can be easily added to represent performance benchmarks, unit tests, and other quantitative and qualitative (e.g. image quality comparison) measurements. Available through OpenBenchmarking.org, a collaborative storage platform developed in conjunction with the Phoronix Test Suite, are more than 200 individual test profiles and more than 60 test suites available by default from the Phoronix Test Suite. Independent users are also able to upload their test results, profiles, and suites to OpenBenchmarking.org. A test profile is a single test that can be executed by the Phoronix Test Suite -- with a series of options possible within every test -- and a test suite is a seamless collection of test profiles and/or additional test suites. A test profile consists of a set of bash/shell scripts and XML files while a test suite is a single XML file. OpenBenchmarking.org also allows for conducting side-by-side result comparisons, a central location for storing and sharing test results, and collaborating over test data. Phoromatic is a complementary platform to OpenBenchmarking.org and the Phoronix Test Suite for interfacing with Phoronix Test Suite client(s) to automatically execute test runs on a timed, per-commit, or other trigger-driven basis. Phoromatic is designed for enterprise and allows for the easy management of multiple networked systems running Phoronix Test Suite clients via a single web-based interface. Professional support and custom engineering for the Phoronix Test Suite, Phoromatic, and OpenBenchmarking.org is available by contacting . Full details on the Phoronix Test Suite setup and usage is available from the included HTML/PDF documentation within the phoronix-test-suite package and from the Phoronix Test Suite web-site. INSTALLATION & SETUP: The Phoronix Test Suite is supported on Linux, *BSD, Solaris, Mac OS X, and Windows systems. However, the most full-featured and well supported operating system for conducting the tests is Linux with some non-basic functionality not being available under all platforms. The Phoronix Test Suite software/framework is compatible with all major CPU architectures (e.g. i686, x86_64, ARM, PowerPC), but not all of the test profiles/suites are compatible with all architectures. The Phoronix Test Suite can be installed for system-wide usage or run locally without installation from the extracted tar.gz/zip package. The only hard dependency on the Phoronix Test Suite is having command-line support for PHP (PHP 5.2+) installed. A complete PHP stack (e.g. with web-server) is NOT needed, but merely the PHP command-line support, which is widely available from operating system package managers under the name php, php5-cli, or php5. USAGE: The process to download, install/setup, execute, and report the results of a benchmark can be as simple as a command such as *phoronix-test-suite benchmark smallpt* to run a simple CPU test profile. If wishing to simply install a test, it's a matter of running *phoronix-test-suite install * and to run it's *phoronix-test-suite run *. There's also a batch mode for non-interactive benchmarking by first running *phoronix-test-suite batch-setup* and then using the *batch-run* sub-command rather than *run*. Viewing installed system hardware and software is available via *phoronix-test-suite system-info* or *phoronix-test-suite detailed-system-info* for greater verbosity. Facilitating a result comparison from OpenBenchmarking.org can be done by running, for example, *phoronix-test-suite benchmark 1204293-BY-PHORONIX357* if wishing to compare the results of the *http://openbenchmarking.org/result/1204293-BY-PHORONIX357* result file. Additional information is available from the Phoronix Test Suite web-site and the material bundled within the phoronix-test-suite/documentation/ directory. A man page is also bundled with the phoronix-test-suite software. phoronix-test-suite/documentation/stubs/50_general_information.html0000644000175000017500000002405012001033143026027 0ustar michaelmichael General Information

    Frequently Asked Questions

    Q: May I use the Phoronix Test Suite when running benchmarks for my own publication or blog? Are there any publishing restrictions?

    A: Anyone is more than welcome to use the Phoronix Test Suite for their own publication or purpose. While the Phoronix Test Suite came out of our internal test tools for carrying out Linux hardware reviews at Phoronix.com, we invite other hardware review web-sites, technology journals, and independent publications to use our software too. While not required, we would just kindly ask that you mention in your review/article that the Phoronix Test Suite was used for carrying out your testing, and ideally to link to www.phoronix-test-suite.com so that your readers will know where to obtain the software if they are interested in running the tests. You are also more than welcome to upload your results to OpenBenchmarking.org so that others may compare their results against yours in an easy manner.

    We also try to make the Phoronix Test Suite easy-to-use by independent publications. For example, if you would like to watermark your web-site's URL into the graphs containing your test results, that can be easily modified in ~/.phoronix-test-suite/graph-config.json. The colors and other graph settings are also stored in this XML file. If you are a publication and run into any issues with the Phoronix Test Suite or have a feature request, please let us know.

    A partial list of other publications using the Phoronix Test Suite can be found in this forum thread.

    Q: Why does the Phoronix Test Suite not use my distribution's package management system for acquiring all needed packages?

    A: The tests themselves are generally downloaded from source and built locally on the machine, rather than fetching any distribution-specific packages. This is done to ensure more comparable results across operating systems / releases, etc. The distribution packager could be applying a number of unknown patches to the software, building the software with unique build options, or making other changes to the software that could skew the results.

    Q: Besides being a developer, documentation writer, or having any other unique technical abilities, how else can I contribute to the Phoronix Test Suite?

    A: Independent code contributions are very welcome as well as creating your own test profiles and suites. We also appreciate any feedback, comments, or other ideas either by emailing us, posting on the forums, or sending a message to the mailing list. You can also see this (outdated) forum thread.

    Q: Do you offer technical support for the Phoronix Test Suite

    A: Paid, professional support is available and is done via our commercial services. We also offer Phoromatic licenses for use within a corporate intranet and other custom services. Free, community support is offered via our mailing list, IRC channel (#phoronix on FreeNode.net, and the Phoronix Forums.

    Q: May I put the Phoronix Test Suite logo on my company's web-site or on my product packaging?

    A: Contact us for licensing information and details regarding the Phoronix Certification & Qualification Suite.

    Q: How often is the Phoronix Test Suite updated?

    A: We provide major updates on a quarterly basis with an occasional point release to fix outstanding bugs or address other issues. The latest work going into the Phoronix Test Suite is accessible via our Git repository at Phorogit.com.

    Tips & Tricks

    General

    - The desktop's screensaver will automatically be shutdown when a test is running and will be restored to its previous state upon the test's completion. This is supported for GNOME, KDE, and other XDG-supportive desktop environments.

    - If you have many computers you wish to benchmark, once all of your tests have been downloaded, run phoronix-test-suite make-download-cache to generate a copy of these files at ~/.phoronix-test-suite/download-cache/. A download cache is used for conserving time and bandwidth by eliminating the need for the Phoronix Test Suite to download files that have already been downloaded once. Copy this folder to the other systems or copy it to a DVD or USB hard drive, connect it to the next test system, and the Phoronix Test Suite will automatically use this local download cache. Or store these files on a local HTTP/FTP server and then update your ~/.phoronix-test-suite/user-config.xml file to reflect the location of this download cache directory.

    Running

    - When running a test in batch mode (through the use of the batch-run or batch-benchmark options) that normally has end-user options (such as the sub-test to run or resolution), the Phoronix Test Suite will run the test with each unique combination of options possible, if configured appropriately.

    - When running a test where you are prompted to enter any test options, multiple selections can be performed -- which will result in multiple test runs for each combination of the selected option(s) -- by separating each intended test option / number with a comma.

    - When being prompted for the test identifier or the file name for saving the results, several user variables are supported. These include $VIDEO_RESOLUTION, $VIDEO_CARD, $OPERATING_SYSTEM, $PROCESSOR, $MOTHERBOARD, $CHIPSET, and $KERNEL_VERSION. If any of these variables are entered, the Phoronix Test Suite will replace them with their respective values before saving the results.

    - If RemoveDownloadFiles is set to TRUE within the user-config.xml file, once a test has been installed the originally downloaded files for that test will be automatically removed. This conserves disk space but will cause these files to be re-downloaded the next time the test needs to be re-installed. This will also not back up the downloaded files to the Phoronix Test Suite download cache. Enabling this option is just recommended for users with very limited disk space.

    - If the amount of video memory for your graphics card is incorrectly reported by the Phoronix Test Suite (you can check by running phoronix-test-suite diagnostics), you can use the VIDEO_MEMORY= environment variable for overriding the video memory capacity (in Megabytes) used by the Phoronix Test Suite.

    - If the DISPLAY environment variable is not set or NO_GRAPHICS_TESTS environment variable is set, tests of type Graphics will not be run. Likewise, if NO_SYSTEM_TESTS environment variable is set, tests of type System will not run. This applies to all test types where NO_<TEST TYPE>_TESTS is set.

    - If while running multiple tests you want to quit the testing prematurely, in a new terminal window type touch ~/.phoronix-test-suite/halt-testing. All results for tests that had already run will be saved (permitting you opted to save the results), except for the test currently being run.

    - If you wish to stop the current test run prematurely but continue the testing process, in a new terminal window type touch ~/.phoronix-test-suite/skip-test.

    - If you want the specified test(s) to run in a loop for a set period of time, use the TOTAL_LOOP_TIME environment variable. For instance, running TOTAL_LOOP_TIME=120 phoronix-test-suite benchmark ffmpeg would keep running the ffmpeg test profile for 120 minutes.

    - If you want the specified test(s) to run in a loop for a set number of times, use the TOTAL_LOOP_COUNT environment variable. For instance, running TOTAL_LOOP_COUNT=3 phoronix-test-suite benchmark ffmpeg would keep running the ffmpeg test profile three times.

    - When any tests are being installed and when tests are being run, a lock is created in the system's temporary directory with the name phoronix-test-suite.active (i.e. /tmp/phoronix-test-suite.active) and is removed upon completion. Thus if you have any system scripts that you wish to run when tests are not running or being installed as to not impact the results, one simple way to handle this is by having the script check for the existence of this lock.

    Configuration

    - The user configuration options for the Phoronix Test Suite are stored in ~/.phoronix-test-suite/user-config.xml. The batch mode options are also stored within this file and those can be adjusted by running phoronix-test-suite batch-setup.

    - The colors, size, and other attributes for the graphs found within the Phoronix Test Suite Results Viewer can be modified via the file ~/.phoronix-test-suite/graph-config.json.

    Test / Suite Writing

    - The Phoronix Test Suite recursively determines tests/suites and allows a suite to call another suite.

    Module Writing

    - By writing a Phoronix Test Suite module, you can easily extend the functionality of the Phoronix Test Suite. Some examples are being able to email the results upon completion, controlling the system's screensaver, updating a text LCD panel with the current test status, etc.

    phoronix-test-suite/documentation/stubs/downloads.html0000644000175000017500000000260411564542013023512 0ustar michaelmichael

    Download Cache For Tests

    If you are a company or simply own multiple computers, the download caching support of the Phoronix Test Suite can work quite well. This feature allows you to very simply setup a local (or network-wide) repository for the Phoronix Test Suite of all the files the different tests use. After you have installed the tests on one system that you normally use (or have ran phoronix-test-suite install all) running phoronix-test-suite make-download-cache will cache all of the files that each test downloaded. The location of this cache is ~/.phoronix-test-suite/download-cache/.

    Once the cache has been created, you can copy this folder to other systems and place the files in the same location. Then when the Phoronix Test Suite needs to download a file for a test, before downloading it from the Internet it will first check this cache for the file(s). If the files are there and the MD5 check-sums have been verified, it will simply copy the file -- thereby saving bandwidth and time. The download cache location can be downloaded in ~/.phoronix-test-suite/user-config.xml. By adjusting the download cache, you could setup the cache folder to be on an FTP or NFS share (as an example) on a server that's accessible via your LAN. Configure your test systems to use this local repository and you will be saving time and bandwidth.

    phoronix-test-suite/documentation/stubs/69_pts_os.html0000644000175000017500000001413311564542013023345 0ustar michaelmichael PTS Desktop Live

    PTS Desktop Live 2010.1 "Anzhofen"

    PTS Desktop Live and PTS Netbook Live are Linux-based operating systems designed to provide a free software platform for carrying out system tests and hardware benchmarks in an automated, reproducible, and effective manner. The Phoronix Test Suite operating systems are designed around the Phoronix Test Suite with the operating system itself consisting of a stripped down Linux environment, then built upon that is the Phoronix Test Suite with its test profiles and suites. This is not a standard Linux desktop with the normal throng of packages.

    Testing with PTS Desktop Live is intended to be via a Live DVD or Live USB (i.e. flash drive or memory card) environment. PTS Netbook Live is similar to PTS Desktop Live but designed for testing on lightweight x86 systems and netbooks. Both PTS Desktop Live and PTS Netbook Live make it very easy to deploy the Phoronix Test Suite across an array of systems, isolates any software differences when seeking to perform hardware comparisons, and is designed to be very easy to carry out these Linux benchmarks even for a first-time Linux user.

    The inaugural release of this operating system was PTS Desktop Live 2009.3 (codenamed "Gernlinden") and was based upon the Phoronix Test Suite 2.0 release. The Gernlinden release shipped with more than 50 open-source test profiles and all needed files being located on the disc image. PTS Desktop Live uses the GTK2 GUI dialog for the Phoronix Test Suite by default, but the CLI options are also accessible. PTS Desktop Live also features optimizations to the Linux kernel and related components for use on the latest high-end hardware and other performance related tweaking. PTS Netbook Live features optimizations for the Intel Atom processor.

    The mission of the Phoronix Test Suite and related products will not be achieved until it has made Linux benchmarking incredibly robust and innovative, drop dead easy to perform nearly any kind of benchmark, and when it out-paces other leading operating systems for its benchmarking abilities. These operating systems are being updated quarterly in conjunction with new Phoronix Test Suite releases. The Phoronix Test Suite will continue to be supported under all other Linux distributions, OpenSolaris, Mac OS X, Windows, and *BSD operating systems, but this is just another addition on top of that.

    PTS Desktop Live is designed to run on x86_64 compatible systems with 2GB or more of system memory (ideally 4GB+ if you wish to run many of the tests in a live environment) being highly recommended along with a modern CPU and graphics processor. No proprietary graphics drivers are shipped with PTS Desktop Live at this time, so depending upon the hardware you may not have OpenGL acceleration to run the few graphics-related tests that are included with this release. Only graphics drivers are provided for ATI/AMD, NVIDIA, and Intel hardware. An Internet connection is not required but is needed for communication with OpenBenchmarking.org and for utilizing some of the other Phoronix Test Suite features.

    PTS Netbook Live is designed for netbooks and nettop computers with an Intel Atom processor.

    Quick Start Guide

    When the operating system has fully booted, the end-user agreement for the Phoronix Test Suite will be displayed, followed by initializing the main GTK user interface for the Phoronix Test Suite. The Phoronix Test Suite has more than 100 test profiles while there are about 50 test profiles featured within live environment, which are free software, do not pose significant install size problems, and are suitable for benchmarking from a live environment. By default, PTS Desktop Live and PTS Netbook Live will only show the test profiles and suites where all of the needed test files and dependencies ship with this open-source operating system. However, to access any of the test profiles that may require downloading additional files or external dependencies, use the View menu to toggle the different options. The system's hardware and software information can also be viewed in a graphical window from this menu.

    From the Available Tests tab, any test/suite can be selected to view more information. If you wish to install the test, simply click on the install button while waiting shortly for it to install. Afterwards, the test can be run by selecting it again and clicking on the run/benchmark button. If you have a OpenBenchmarking.org account, you can login from the File menu while Phoronix Test Suite settings are adjustable from the Edit menu.

    When the testing has completed, the graphical user interface will reappear. Via the buttons that appear at the top of the interface, the test results can then be opened within the web browser. Depending upon the test profile, it may also be possible to immediately compare the test result(s) against a set of reference systems. If the completed test(s) do have reference results available, a list of the comparable systems are shown, so that you can click on one or more of these reference systems to see how the given system performs in comparison. Results from OpenBenchmarking.org can also be compared with any of the test results.

    Assuming you did not launch any commands from the terminal to alter the disk(s) or its contents or carry out any other changes; PTS Desktop Live will have not touched your data or the installed operating system(s). If you wish to archive any of your test results, upload the results to OpenBenchmarking.org. Alternatively, when going to the Test Results tab and selecting a test, the File menu presents options for exporting results to text, CSV, and PDF files. The contents of the ~/.phoronix-test-suite/test-results/ folder can also be backed up for preserving the test results.

    If you wish to use the Phoronix Test Suite from the command-line, open a terminal and run phoronix-test-suite.

    phoronix-test-suite/documentation/stubs/60_phoromatic.html0000644000175000017500000000405511564542013024174 0ustar michaelmichael Phoromatic

    Overview

    Phoromatic is a remote management system for the Phoronix Test Suite. Phoromatic allows the automatic (hence the name Phoromatic) scheduling of tests, remote installation of new tests, and the management of multiple test systems all through an intuitive, easy-to-use web interface. Tests can be scheduled to automatically run on a routine basis across multiple test systems. The test results are then available from this central, secure location.

    Basic Instructions

    1. Create a free account at Phoromatic.com. Phoromatic can also be installed on a LAN / intranet for professional and enterprise support customers of the Phoronix Test Suite.
    2. On each test system, install the latest version of the Phoronix Test Suite and then run phoronix-test-suite module-setup phoromatic. During this process it will ask the user for an account code and activiation ID that are shown from the Systems page of your Phoromatic account.
    3. Phoromatic cannot install external dependencies for a test if the Phoronix Test Suite is not running as root, so it would be recommended to now run phoronix-test-suite install-dependencies all. Alternatively, you can also run phoronix-test-suite install all to install all tests at this time, or begin selectively installing the tests you wish to use. Phoromatic can install tests automatically though, it just cannot install external dependencies when the user is not root.
    4. When you are all set, run phoronix-test-suite phoromatic.start, which begins the process of the Phoronix Test Suite listening to the Phoromatic server waiting for installation and run commands, etc. The installed system software/hardware is also reported all automatically, etc.

    For more information on Phoromatic and a detailed guide, read Building A Benchmarking Test Farm With Phoromatic.

    phoronix-test-suite/documentation/stubs/55_virtual_suites.html0000644000175000017500000001610112223157104025104 0ustar michaelmichaelVirtual Test Suites

    Virtual test suites are not like a traditional test suite defined by the XML suite specification. Virtual test suites are dynamically generated in real-time by the Phoronix Test Suite client based upon the specified test critera. Virtual test suites can automatically consist of all test profiles that are compatible with a particular operating system or test profiles that meet other critera. When running a virtual suite, the OpenBenchmarking.org repository of the test profiles to use for generating the dynamic suite must be prefixed.

    Virtual test suites can be installed and run just like a normal XML test suite and shares nearly all of the same capabilities. However, when running a virtual suite, the user will be prompted to input any user-configuration options for needed test profiles just as they would need to do if running the test individually. When running a virtual suite, the user also has the ability to select individual tests within the suite to run or to run all of the contained test profiles. Virtual test suites are also only supported for an OpenBenchmarking.org repository if there is no test profile or test suite of the same name in the repository. Below is a list of common virtual test suites for the main Phoronix Test Suite repository, but the dynamic list of available virtual test suites based upon the enabled repositories is available by running phoronix-test-suite list-available-virtual-suites.


    All PTS Tests pts/all

    This is a collection of all test profiles found within the specified OpenBenchmarking.org repository.

    Installed Tests pts/installed

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository that are already installed on the system under test.

    Linux Operating System Tests pts/linux

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being compatible with the Linux Operating System.

    Solaris Operating System Tests pts/solaris

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being compatible with the Solaris Operating System.

    BSD Operating System Tests pts/bsd

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being compatible with the BSD Operating System.

    MacOSX Operating System Tests pts/macosx

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being compatible with the MacOSX Operating System.

    Windows Operating System Tests pts/windows

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being compatible with the Windows Operating System.

    Hurd Operating System Tests pts/hurd

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being compatible with the Hurd Operating System.

    System Subsystem Tests pts/system

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a test of the System sub-system.

    Processor Subsystem Tests pts/processor

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a test of the Processor sub-system.

    Graphics Subsystem Tests pts/graphics

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a test of the Graphics sub-system.

    Other Subsystem Tests pts/other

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a test of the Other sub-system.

    Utility Tests pts/utility

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a Utility software test.

    Simulator Tests pts/simulator

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a Simulator software test.

    Scientific Tests pts/scientific

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a Scientific software test.

    Benchmark Tests pts/benchmark

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a Benchmark software test.

    Application Tests pts/application

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a Application software test.

    Game Tests pts/game

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a Game software test.

    Smp Tests pts/smp

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified via an internal tag as testing smp.

    Python Tests pts/python

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified via an internal tag as testing python.

    Mpi Tests pts/mpi

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified via an internal tag as testing mpi.

    Openmp Tests pts/openmp

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified via an internal tag as testing openmp.

    Cuda Tests pts/cuda

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified via an internal tag as testing cuda.

    Vdpau Tests pts/vdpau

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified via an internal tag as testing vdpau.

    Video Tests pts/video

    This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified via an internal tag as testing video.

    phoronix-test-suite/documentation/stubs/00_user_options.html0000644000175000017500000005116612223157103024552 0ustar michaelmichaelUser Options

    The following options are currently supported by the Phoronix Test Suite client. A list of available options can also be found by running phoronix-test-suite help.


    Test Installation

    install [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option will install the selected test(s) inside the testing environment directory). The install process from downloading of the test files to the installation is fully automated. The install option needs to be supplied with the test name or suite as an argument. Optionally, a OpenBenchmarking.org ID or the name of a saved results file can be supplied as well and the test(s) to install will automatically be extracted from that information. If the test is already installed and was run by the latest version of the installation process, no action will be taken. Multiple arguments can be supplied to install additional tests at the same time.

    install-dependencies [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option will install the external dependencies needed by the selected test(s) using the distribution's package management system. For example, some tests depend upon GCC for compiling code. If GCC is not detected on the system, the Phoronix Test Suite will attempt to install GCC using the distribution's package management system. If you are running this command as a local user, you may be prompted for the root password while the process is running. For unsupported distributions, the dependency names will be displayed along with common names for the package. The install-dependencies option needs to be supplied with the test name or suite as an argument. When using the install option, the external dependencies are automatically checked.

    make-download-cache

    This option will create a download cache for use by the Phoronix Test Suite.

    remove-installed-test [Test]

    This option will permanently remove a installed test by the Phoronix Test Suite.

    Testing

    auto-compare

    This option will autonomously determine the most relevant test(s) to run for any selected sub-system(s). The tests to run are determined via OpenBenchmarking.org integration with the global results pool. Related test results from OpenBenchmarking.org are also merged to provide a straight-forward and effective means of carrying out a system comparison. If wishing to find comparable results for any particular test profile(s), simply pass the test profile names as additional arguments to this command.

    benchmark [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option will install the selected test(s) (if needed) and will proceed to run the test(s). This option is equivalent to running phoronix-test-suite with the install option followed by the run option. Multiple arguments can be supplied to run additional tests at the same time and save the results into one file.

    finish-run [Test Result]

    This option can be used if a test run had not properly finished running all tests within a saved results file. Using this option when specifying a saved results file where all tests had not completed will attempt to finish testing on the remaining tests where there are missing results.

    run [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option will run the selected test(s).

    run-tests-in-suite

    This option can be used if you wish to run all of the tests found in a supplied suite, but you wish to re-configure each of the test options rather than using the defaults supplied by the suite.

    Batch Testing

    batch-benchmark [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option and its arguments are equivalent to the benchmark option, but the process will be run in the Phoronix Test Suite batch mode.

    batch-install [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    If you wish to run the install process in the Phoronix Test Suite batch mode but do not wish to run any tests at this time. Running the install process in the batch mode will use the default values and not prompt the user of any possible options, to ensure the process is fully automated.

    batch-run [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option and its arguments are equivalent to the run option, but the process will be run in the Phoronix Test Suite batch mode.

    batch-setup

    This option is used to configure the batch mode options for the Phoronix Test Suite, which is subsequently written to the user configuration file. Among the options are whether to automatically upload the test results to OpenBenchmarking.org and prompting for the saved file name.

    default-benchmark [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option will install the selected test(s) (if needed) and will proceed to run the test(s) in the defaults mode. This option is equivalent to running phoronix-test-suite with the install option followed by the default-run option.

    default-run [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option will run the selected test(s). The name of the test or suite must be supplied or the OpenBenchmarking.org ID or saved local file name. Multiple arguments can be supplied to run additional tests at the same time and save the results in a suite-like fashion. Unlike the normal run option, the default-run will not prompt the user to select from the available test options but will instead use the default options as automatically set by pts-core or the test profile. Use batch-run to automatically test all of the available options.

    internal-run [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option and its arguments pre-set the Phoronix Test Suite batch run mode with sane values for carrying out benchmarks in a semi-automated manner and without uploading any of the result data to the public OpenBenchmarking.org.

    OpenBenchmarking.org

    clone-result [OpenBenchmarking ID] ...

    This option will download a local copy of a file that was saved to OpenBenchmarking.org, as long as a valid public ID is supplied. More than one ID can be specified and the results will then be merged.

    list-recommended-tests

    This option will list recommended test profiles for benchmarking sorted by hardware sub-system. The recommended tests are determined via querying OpenBenchmarking.org and determining the most popular tests for a given environment based upon the number of times a test profile has been downloaded, the number of test results available on OpenBenchmarking.org for a given test profile, the age of the test profile, and other weighted factors.

    openbenchmarking-changes

    This option will list recent changes to test profiles of enabled OpenBenchmarking.org repositories.

    openbenchmarking-launcher

    This option is called automatically with the .openbenchmarking MIME file extension support for launching OpenBenchmarking.org operations.

    openbenchmarking-login

    This option is used for controlling your Phoronix Test Suite client options for OpenBechmarking.org and syncing the client to your account.

    openbenchmarking-refresh

    This option is used for refreshing the stored OpenBenchmarking.org repostory information and other data. The Phoronix Test Suite will automatically refresh this data every three days or when other thresholds are exceeded, but this command can be used to manually refresh/updates the data.

    openbenchmarking-repositories

    This option will list the OpenBenchmarking.org repositories currently linked to this Phoronix Test Suite client instance.

    upload-result [Test Result]

    This option is used for uploading a test result to OpenBenchmarking.org.

    upload-test-profile

    This option can be used for uploading a test profile to your account on OpenBenchmarking.org. By uploading your test profile to OpenBenchmarking.org, others are then able to browse and access this test suite for easy distribution in a seamless manner by other Phoronix Test Suite clients.

    upload-test-suite

    This option can be used for uploading a test suite to your account on OpenBenchmarking.org. By uploading your test suite to OpenBenchmarking.org, others are then able to browse and access this test suite for easy distribution.

    System

    detailed-system-info

    Display detailed information about the installed system hardware and software information as detected by the Phoronix Test Suite Phodevi Library.

    diagnostics

    This option will print information that is useful to developers when debugging problems with the Phoronix Test Suite and/or test profiles and test suites.

    interactive

    A simple text-driven interactive interface to the Phoronix Test Suite.

    system-info

    Display the installed system hardware and software information as detected by the Phoronix Test Suite Phodevi Library.

    system-sensors

    Display the installed system hardware and software sensors in real-time as detected by the Phoronix Test Suite Phodevi Library.

    Information

    info [Test | Suite | OpenBenchmarking.org ID | Test Result]

    This option will show details about the supplied test, suite, virtual suite, or result file.

    list-available-suites

    This option will list all test suites that are available from the enabled OpenBenchmarking.org repositories.

    list-available-tests

    This option will list all test profiles that are available from the enabled OpenBenchmarking.org repositories.

    list-available-virtual-suites

    This option will list all available virtual test suites that can be dynamically created based upon the available tests from enabled OpenBenchmarking.org repositories.

    list-installed-dependencies

    This option will list all of the packages / external test dependencies that are already installed on the system that the Phoronix Test Suite may potentially depend upon by test profiles.

    list-installed-suites

    This option will list all suites that are currently installed on the system.

    list-installed-tests

    This option will list all test profiles that are currently installed on the system.

    list-missing-dependencies

    This option will list all of the packages / external test dependencies that are missing from the system that the Phoronix Test Suite may potentially need by select test profiles.

    list-possible-dependencies

    This option will list all of the packages / external test dependencies that are are potentially used by the Phoronix Test Suite.

    list-saved-results

    This option will list all of the saved test results found on the system.

    list-test-usage

    This option will list various details about installed tests and their usage.

    list-unsupported-tests

    This option will list all available test profiles that are available from the enabled OpenBenchmarking.org repositories but are NOT SUPPORTED on the given hardware/software platform. This is mainly a debugging option for those looking for test profiles to potentially port to new platforms, etc.

    Asset Creation

    debug-install [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option is intended for use by test profile writers and is identical to the install option but will yield more information during the run process that can be used to debug issues with a test profile installer or to verify the test profile is functioning correctly.

    debug-run [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option is intended for use by test profile writers and is identical to the <em>run</em> option but will yield more information during the run process that can be used to debug issues with a test profile or to verify the test profile is functioning correctly.

    debug-test-download-links [Test | Suite]

    This option will check all download links within the specified test profile(s) to ensure there are no broken URLs.

    download-test-files [Test | Suite] ...

    This will download the selected test file(s) to the Phoronix Test Suite download cache but will not install the tests.

    force-install [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option will force the installation (or re-installation) of a test or suite. The arguments and process is similar to the install option but even if the test is installed, the entire installation process will automatically be executed. This option is generally used when debugging a test installation problem.

    result-file-to-suite [Test Result]

    This option will guide the user through the process of generating their own test suite, which they can then run, that is based upon an existing test results file.

    validate-result-file

    This option can be used for validating a Phoronix Test Suite result file as being compliant against the OpenBenchmarking.org specification.

    validate-test-profile

    This option can be used for validating a Phoronix Test Suite test profile as being compliant against the OpenBenchmarking.org specification.

    validate-test-suite

    This option can be used for validating a Phoronix Test Suite test suite as being compliant against the OpenBenchmarking.org specification.

    Result Management

    copy-run-in-result-file [Test Result]

    This option is used if you wish to change an existing test run within a saved results file.

    extract-from-result-file [Test Result]

    This option will extract a single set of test results from a saved results file that contains multiple test results that have been merged. The user is the prompted to specify a new result file name and select which result identifier to extract.

    merge-results [Test Result] ...

    This option will manually merge multiple sets of test results generated by the Phoronix Test Suite.

    refresh-graphs [Test Result]

    This option will re-render and save all result graphs within a saved file. This option can be used when making modifications to the graphing code or its color/option configuration file and testing the changes.

    remove-from-result-file [Test Result]

    This option is used if there is a set of test results you wish to remove/delete from a saved results file. The user must specify a saved results file and then they will be prompted to select the results identifier associated with the results they wish to remove.

    remove-result [Test Result]

    This option will permanently remove the saved file set that is set as the first argument.

    rename-identifier-in-result-file [Test Result]

    This option is used if you wish to change the name of the identifier in a test results file that is shown in the Phoronix Test Suite Results Viewer and the contained graphs.

    reorder-result-file [Test Result]

    This option is used if you wish to change the order in which test results are shown in the Phoronix Test Suite Results Viewer and the contained graphs. The user must specify a saved results file and then they will be prompted to select the results identifiers one at a time in the order they would like them to be displayed from left to right.

    result-file-to-csv [Test Result]

    This option will read a saved test results file and output the system hardware and software information along with the results to a CSV output. The CSV (Comma Separated Values) output can then be loaded into a spreadsheet for easy viewing.

    result-file-to-pdf [Test Result]

    This option will read a saved test results file and output the system hardware and software information along with the results to a PDF file.

    result-file-to-text [Test Result]

    This option will read a saved test results file and output the system hardware and software information to the terminal. The test results are also outputted.

    show-result [Test Result]

    Open up the test results in the Phoronix Test Suite Result Viewer or on OpenBenchmarking.org.

    Result Analytics

    analyze-all-runs [Test Result]

    This option will generate a candlestick graph showing the distribution of results from all trial runs. The candlestick graph is similar to the Japanese candlestick charts used by the financial industry, except instead of representing stock data it is numerical result data from all trial runs.\n\nThe tip of the upper-wick represents the highest value of the test runs with the tip of the lower-wick representing the lowest value of all test runs. The upper-edge of the candle body represents the first or last run value and the lower-edge represents the first or last run value. Lastly, if the last run value is less than the first run value, the candle body is the same color as the graph background, otherwise the last run value is greater.

    analyze-batch [Test Result]

    This option will analyze a batch results file and plot out the performance impact from the different options onto a line graph (i.e. to see the impact that changing the video resolution has on the system's performance).

    analyze-image-delta [Test Result]

    This option will analyze a test result file if it contains any test results that produced an image quality comparison (IQC) and will render image deltas illustrating the difference between images from two test results.

    Other

    build-suite

    This option will guide the user through the process of generating their own test suite, which they can then run. Optionally, passed as arguments can be the test(s) or suite(s) to add to the suite to be created, instead of being prompted through the process.

    debug-self-test

    This option is used during the development of the Phoronix Test Suite software for testing of internal interfaces, commands, and other common code-paths. The produced numbers should only be comparable for the same version of the Phoronix Test Suite, on the same hardware/software system, conducted on the same day of testing. This isn't intended as any scientific benchmark but simply to stress common PHP code-paths and looking for hot areas to optimize, etc.

    help

    This option will display the list of available Phoronix Test Suite commands.

    network-setup

    This option allows the user to configure how the Phoronix Test Suite connects to OpenBenchmarking.org and other web-services. Connecting through an HTTP proxy can be configured through this option.

    rebuild-composite-xml [Test Result]

    This option can be used to rebuild your composite XML file in the event that the main result file was corrupted and the test-X.xml files are still present in the result file directory.

    user-config-reset

    This option can be used for resetting the Phoronix Test Suite user configuration file to its default state.

    user-config-set

    This option can be used for setting an XML value in the Phoronix Test Suite user configuration file.

    version

    This option will display the Phoronix Test Suite client version.

    Modules

    list-modules

    This option will list all of the available Phoronix Test Suite modules on this system.

    module-info [Phoronix Test Suite Module]

    This option will show detailed information on a Phoronix Test Suite module such as the version, developer, and a description of its purpose.

    module-setup [Phoronix Test Suite Module]

    This option will allow you to configure all available end-user options for a Phoronix Test Suite module. These options are then stored within the user's configuration file. Not all modules may have options that can be configured by the end-user.

    test-module [Phoronix Test Suite Module]

    This option can be used for debugging a Phoronix Test Suite module.

    phoronix-test-suite/documentation/stubs/59_component_testing.html0000644000175000017500000000761711727523673025621 0ustar michaelmichael Component Testing

    Compiler Testing & Masking

    A majority of the test profiles provided by OpenBenchmarking.org to the Phoronix Test Suite are source-based tests. Relying upon the upstream source-code for each program under test allows for the tests to be easily brought to new platforms and architectures, avoids any out-of-tree / non-default packaging differences by different distributions and operating systems, and to allow the Phoronix Test Suite user to easily test new compilers and/or compiler options. For the source-based tests, the Phoronix Test Suite relies upon a compiler (e.g. GCC, LLVM/Clang, Sun Studio, Open64, et al) being present on the system under test. The Phoronix Test Suite does respect CC/CXX environment variables and test profiles are expected to honor CFLAGS/CXXFLAGS and other compiler settings.

    As of Phoronix Test Suite 3.8, a compiler masking method is utilized for logging compiler options and other settings with each test profile installation. Prior to installing an open-source test, the Phoronix Test Suite determines the intended compiler to be used based upon the pre-set environment variables or the pre-set compiler(s) within the PATH environment variable. The Phoronix Test Suite then masks the compiler to ensure that any options/flags submitted to the compiler are first passed through pts-core so that they can be logged for later use, then is linked to the original, intended compiler. Additionally, other compiler binary names of the same type are blacklisted to prevent their un-intended use (i.e. if a test profile has hard-coded gcc in its build script, but clang is set as the compiler via CC, a sym-link will automatically be created from gcc to the masked clang for the duration of its test installation).

    The logged compiler data is then used by the Phoronix Test Suite following the test execution process for automated result analysis. If there is a detected change in compiler settings, the differences are automatically reported to the test result graphs. Additionally, key compiler information (e.g. the compiler optimization level and key libraries that were linked at compile-time) is reported as a footnote on result graphs. The Phoronix Test Suite handles all of this in a fully automated manner; test profiles require no changes to take advantage of these compiler-reporting capabilities.

    Separately, the Phoronix Test Suite attempts to automatically log the system compiler's build configuration (i.e. GCC's gcc -v "Configured with") output. If the Phoronix Test Suite detects there is a compiler build configuration change between test runs in a result file, it will report each compiler's build configuration to the system information table within the results viewer. Reported to the table is a reduced view of the build configuration options, with less relevant items being stripped away from this view to reduce verbosity. Upon clicking the text, the raw compiler information output can be viewed in full.

    Disk / File-System Testing

    By default tests are installed to ~/.phoronix-test-suite/installed-tests/. However, the location can be updated from ~/.phoronix-test-suite/user-config.xml or dynamically via the PTS_TEST_INSTALL_ROOT_PATH environment variable.

    When any disk tests are executed, the Phoronix Test Suite will attempt to log the mount options and scheduler of the disk/partition being used for testing. This information is subsequently displayed within the system information table. If the scheduler / mount options are maintained the same throughout all test runs, only a single line is displayed otherwise the options for each test run will be automatically displayed. The file-system in use is always captured and shown in the system information table.

    phoronix-test-suite/pts-core/phoronix-test-suite.php0000644000175000017500000001212512202227535023036 0ustar michaelmichael. */ setlocale(LC_NUMERIC, 'C'); define('PTS_PATH', dirname(dirname(__FILE__)) . '/'); // PTS_MODE types // CLIENT = Standard Phoronix Test Suite Client // LIB = Only load select PTS files // SILENT = Load all normal pts-core files, but don't run client code if(!defined('PTS_MODE')) { define('PTS_MODE', in_array(($m = getenv('PTS_MODE')), array('CLIENT', 'LIB', 'SILENT')) ? $m : 'CLIENT'); } // Any PHP default memory limit should be fine for PTS, until you run image quality comparison tests that begins to consume memory ini_set('memory_limit', '256M'); require(PTS_PATH . 'pts-core/pts-core.php'); if(!PTS_IS_CLIENT) { // pts-core is acting as a library, return now since no need to run client code return; } pts_define('IS_PTS_WEB_INTERFACE', php_sapi_name() == 'cli-server'); if(IS_PTS_WEB_INTERFACE == 'cli-server') { $argv = array(); $argv[1] = 'webui'; $argc = count($argv); } // Default to C locale setlocale(LC_ALL, 'C'); if(ini_get('date.timezone') == null) { $tz = null; // timezone_name_from_abbr was added in PHP 5.1.3. pre-5.2 really isn't supported by PTS, but don't at least error out here but let it get to proper checks... if(is_executable('/bin/date') && function_exists('timezone_name_from_abbr')) { $tz = timezone_name_from_abbr(trim(shell_exec('date +%Z 2> /dev/null'))); } if($tz == null || !in_array($tz, timezone_identifiers_list())) { $tz = 'UTC'; } date_default_timezone_set($tz); } if(ini_get('open_basedir') != false) { if(pts_client::open_basedir_check() == false) { echo PHP_EOL . 'ERROR: The php.ini configuration open_basedir directive is preventing ' . PTS_PATH . ' from loading.' . PHP_EOL; return false; } else { trigger_error('The php.ini configuration is using the "open_basedir" directive, which may prevent some parts of the Phoronix Test Suite from working. See the Phoronix Test Suite documentation for more details and to disable this setting.', E_USER_WARNING); } } // Needed for shutdown functions // declare(ticks = 1); $sent_command = strtolower(str_replace('-', '_', (isset($argv[1]) ? $argv[1] : null))); $quick_start_options = array('dump_possible_options'); pts_define('QUICK_START', in_array($sent_command, $quick_start_options)); if(QUICK_START == false && IS_PTS_WEB_INTERFACE == false) { pts_client::program_requirement_checks(true); } pts_client::init(); // Initalize the Phoronix Test Suite (pts-core) client $pass_args = array(); if(is_file(PTS_PATH . 'pts-core/commands/' . $sent_command . '.php') == false) { $replaced = false; if(pts_module::valid_run_command($sent_command)) { $replaced = true; } else if(isset($argv[1]) && strpos($argv[1], '.openbenchmarking') !== false && is_readable($argv[1])) { $sent_command = 'openbenchmarking_launcher'; $argv[2] = $argv[1]; $argc = 3; $replaced = true; } else { $aliases = pts_storage_object::read_from_file(PTS_TEMP_STORAGE, 'command_alias_list'); if($aliases == null) { $aliases = pts_documentation::client_commands_aliases(); } if(isset($aliases[$sent_command])) { $sent_command = $aliases[$sent_command]; $replaced = true; } } if($replaced == false) { // Show help command, since there are no valid commands $sent_command = 'help'; } } pts_define('PTS_USER_LOCK', PTS_USER_PATH . 'run_lock'); if(QUICK_START == false && IS_PTS_WEB_INTERFACE == false) { if(pts_client::create_lock(PTS_USER_LOCK) == false) { pts_client::$display->generic_warning('It appears that the Phoronix Test Suite is already running.' . PHP_EOL . 'For proper results, only run one instance at a time.'); } register_shutdown_function(array('pts_client', 'process_shutdown_tasks')); if(pts_client::read_env('PTS_IGNORE_MODULES') == false) { pts_client::module_framework_init(); // Initialize the PTS module system } } // Read passed arguments for($i = 2; $i < $argc && isset($argv[$i]); $i++) { array_push($pass_args, $argv[$i]); } if(QUICK_START == false && IS_PTS_WEB_INTERFACE == false) { pts_client::user_agreement_check($sent_command); pts_client::user_hardware_software_reporting(); // OpenBenchmarking.org pts_openbenchmarking::refresh_repository_lists(); } pts_client::execute_command($sent_command, $pass_args); // Run command if(QUICK_START == false) { pts_client::release_lock(PTS_USER_LOCK); } ?> phoronix-test-suite/pts-core/user-agreement.txt0000644000175000017500000000606212201552341022035 0ustar michaelmichaelThe Phoronix Test Suite is the most comprehensive testing and benchmarking platform available for Linux, OpenSolaris, Mac OS X, Windows, and BSD operating systems. The Phoronix Test Suite is designed to carry out tests in a clean, reproducible, and easy-to-use manner. - The Phoronix Test Suite is open-source and licensed under the GNU GPLv3. However, some tests supported by the Phoronix Test Suite are not open-source software or available for free of charge. - The Phoronix Test Suite contains tests which may stress your system and in some cases could exhibit stability problems of the system's hardware or software configuration. The Phoronix Test Suite is provided WITHOUT ANY WARRANTY. In no event shall OpenBenchmarking.org, Phoromatic, Phoronix Media, the Phoronix Test Suite, or any associated stakeholder be liable to any party for any direct or indirect damages for any use of OpenBenchmarking.org -- including, without limitation, any lost profits, business interruption, loss of programs, loss of programmed data, or otherwise. - For enterprise support, sponsorship, or other professional inquiries, contact phoronix@phoronix.com. Community support can be found in the Phoronix Forums at http://www.phoronix.com/forums/. - If you opt to submit your test results to OpenBenchmarking.org, the final results as well as basic hardware and software details (what is shown in the results viewer) will be shared and publicly accessible through http://www.openbenchmarking.org/. - Public bug reports, feature requests, and other issues can be brought up in the Phoronix Test Suite forums, mailing list, or a direct email to Phoronix Media. Anonymous Usage Reporting / Statistics: If enabling the anonymous usage reporting / statistics feature, some information about the Phoronix Test Suite runs will be submitted to OpenBenchmarking.org. This information is used for analytical purposes, including but not limited to, determining the most popular tests / suites and calculating average run-times for different test profiles. The test results are not reported in this process nor the installed software / hardware information, but ambient information about the testing process. This information is stored anonymously. More information on this feature is available with the included documentation. Anonymous Software / Hardware Reporting: If enabling the anonymous hardware / software reporting, general information on your installed hardware / software components will be reported to OpenBenchmarking.org. Hardware information is general details such as, but not limited to, the installed CPU, motherboard, and other general components. Software information is general and contains details such as your operating system, graphics processor driver, kernel, and software architecture. No personal information is collected. This information is pooled along with the submissions from all other users to show general trends and other details on OpenBenchmarking.org. For more information on the Phoronix Test Suite and its features, visit http://www.phoronix-test-suite.com/ or view the included documentation. phoronix-test-suite/pts-core/pts-core.php0000644000175000017500000001513212223157055020623 0ustar michaelmichael. */ function pts_codename($full_string = false) { $codename = ucwords(strtolower(PTS_CODENAME)); return ($full_string ? 'PhoronixTestSuite/' : null) . $codename; } function pts_title($show_codename = false) { return 'Phoronix Test Suite v' . PTS_VERSION . ($show_codename ? ' (' . pts_codename() . ')' : null); } function pts_define($name, $value = null) { static $defines; if($name === -1) { return $defines; } $defines[$name] = $value; define($name, $value); } function pts_define_directories() { // User's home directory for storing results, module files, test installations, etc. pts_define('PTS_CORE_PATH', PTS_PATH . 'pts-core/'); if(PTS_IS_CLIENT) { pts_define('PTS_USER_PATH', pts_client::user_home_directory() . '.phoronix-test-suite/'); pts_define('PTS_CORE_STORAGE', PTS_USER_PATH . 'core.pt2so'); pts_define('PTS_TEMP_STORAGE', PTS_USER_PATH . 'temp.pt2so'); pts_define('PTS_MODULE_LOCAL_PATH', PTS_USER_PATH . 'modules/'); pts_define('PTS_MODULE_DATA_PATH', PTS_USER_PATH . 'modules-data/'); pts_define('PTS_DOWNLOAD_CACHE_PATH', PTS_USER_PATH . 'download-cache/'); pts_define('PTS_OPENBENCHMARKING_SCRATCH_PATH', PTS_USER_PATH . 'openbenchmarking.org/'); pts_define('PTS_TEST_PROFILE_PATH', PTS_USER_PATH . 'test-profiles/'); pts_define('PTS_TEST_SUITE_PATH', PTS_USER_PATH . 'test-suites/'); pts_define('PTS_RESULTS_VIEWER_PATH', PTS_CORE_PATH . 'results-viewer/'); } else if(defined('PTS_STORAGE_PATH')) { pts_define('PTS_OPENBENCHMARKING_SCRATCH_PATH', PTS_STORAGE_PATH . 'openbenchmarking.org/'); pts_define('PTS_TEST_PROFILE_PATH', PTS_STORAGE_PATH . 'test-profiles/'); pts_define('PTS_TEST_SUITE_PATH', PTS_STORAGE_PATH . 'test-suites/'); } else if(defined('PATH_TO_PHOROMATIC_STORAGE')) { pts_define('PTS_OPENBENCHMARKING_SCRATCH_PATH', PATH_TO_PHOROMATIC_STORAGE . 'openbenchmarking.org/'); pts_define('PTS_TEST_PROFILE_PATH', PATH_TO_PHOROMATIC_STORAGE . 'test-profiles/'); pts_define('PTS_TEST_SUITE_PATH', PATH_TO_PHOROMATIC_STORAGE . 'test-suites/'); } // Misc Locations pts_define('PTS_MODULE_PATH', PTS_CORE_PATH . 'modules/'); pts_define('PTS_CORE_STATIC_PATH', PTS_CORE_PATH . 'static/'); pts_define('PTS_COMMAND_PATH', PTS_CORE_PATH . 'commands/'); pts_define('PTS_EXDEP_PATH', PTS_CORE_PATH . 'external-test-dependencies/'); pts_define('PTS_OPENBENCHMARKING_PATH', PTS_CORE_PATH . 'openbenchmarking.org/'); } function pts_needed_extensions() { return array( // Required? - The Check If In Place - Name - Description // Required extesnions denoted by 1 at [0] array(1, extension_loaded('dom'), 'DOM', 'The PHP Document Object Model (DOM) is required for XML operations.'), array(1, extension_loaded('zip') || extension_loaded('zlib'), 'ZIP', 'PHP Zip support is required for file compression and decompression.'), array(1, function_exists('json_decode'), 'JSON', 'PHP JSON support is required for OpenBenchmarking.org communication.'), // Optional but recommended extensions array(0, extension_loaded('openssl'), 'OpenSSL', 'PHP OpenSSL support is recommended to support HTTPS traffic.'), array(0, extension_loaded('gd'), 'GD', 'The PHP GD library is recommended for improved graph rendering.'), array(0, extension_loaded('zlib'), 'Zlib', 'The PHP Zlib extension can be used for greater file compression.'), array(0, function_exists('pcntl_fork'), 'PCNTL', 'PHP PCNTL is highly recommended as it is required by some tests.'), array(0, function_exists('posix_getpwuid'), 'POSIX', 'PHP POSIX support is highly recommended.'), array(0, function_exists('curl_init'), 'CURL', 'PHP CURL is recommended for an enhanced download experience.'), array(0, is_file('/usr/share/php/fpdf/fpdf.php'), 'PHP FPDF', 'PHP FPDF is recommended if wishing to generate PDF reports.') ); } function pts_version_codenames() { return array( // Sør-Trøndelag - Norway '1.0' => 'Trondheim', '1.2' => 'Malvik', '1.4' => 'Orkdal', '1.6' => 'Tydal', '1.8' => 'Selbu', // Troms - Norway '2.0' => 'Sandtorg', '2.2' => 'Bardu', '2.4' => 'Lenvik', '2.6' => 'Lyngen', '2.8' => 'Torsken', // Aust-Agder - Norway '2.9' => 'Iveland', // early PTS3 development work '3.0' => 'Iveland', '3.2' => 'Grimstad', '3.4' => 'Lillesand', '3.6' => 'Arendal', '3.8' => 'Bygland', // Rogaland - Norway '4.0' => 'Suldal', '4.2' => 'Randaberg', '4.4' => 'Forsand', '4.6' => 'Utsira', '4.8' => 'Sokndal', // Tulskaya oblast / Tula Oblast region - Russia '5.0' => 'Plavsk', '5.2' => 'Khanino', '5.4' => 'Lipki', '5.6' => 'Dedilovo', '5.8' => 'Belev', ); } pts_define('PTS_VERSION', '4.8.3'); pts_define('PTS_CORE_VERSION', 4830); pts_define('PTS_CODENAME', 'SOKNDAL'); pts_define('PTS_IS_CLIENT', (defined('PTS_MODE') && PTS_MODE == 'CLIENT')); pts_define('PTS_IS_DEV_BUILD', (substr(PTS_VERSION, -2, 1) == 'm')); if(!defined('PTS_PATH')) { pts_define('PTS_PATH', dirname(dirname(__FILE__)) . '/'); } pts_define('PTS_PHP_VERSION', phpversion()); if(PTS_IS_CLIENT || defined('PTS_AUTO_LOAD_OBJECTS')) { function pts_build_dir_php_list($dir, &$files) { if($dh = opendir($dir)) { while(($file = readdir($dh)) !== false) { if($file != '.' && $file != '..') { if(is_dir($dir . '/' . $file) && (PTS_IS_CLIENT || $file != 'client')) { // The client folder should contain classes exclusively used by the client pts_build_dir_php_list($dir . '/' . $file, $files); } else if(substr($file, -4) == '.php') { $files[substr($file, 0, -4)] = $dir . '/' . $file; } } } } closedir($dh); } function __autoload($to_load) { static $obj_files = null; if($obj_files == null) { pts_build_dir_php_list(PTS_PATH . 'pts-core/objects', $obj_files); } if(isset($obj_files[$to_load])) { include($obj_files[$to_load]); unset($obj_files[$to_load]); } } } ?> phoronix-test-suite/documentation/TODO0000664000175000017500000000462412202330241020154 0ustar michaelmichaelPHORONIX TEST SUITE PUBLIC TODO LIST: ### PTS-CORE ### - Move External Dependencies into OpenBenchmarking.org cloud - Reporting to OpenBenchmarking.org on broken download URLs for test profiles. - Reporting of install times to OpenBenchmarking.org and also exposing this information back to clients. - Support for multiple languages / internationalization. - BLKID fall-back support for determining file-system [e.g. /sbin/blkid -s TYPE -o value /dev/sda1]. - Possibly restore "weighted suites" [http://phorogit.com/index.php?p=phoronix-test-suite.git&a=commitdiff&h=548e5c073cc90d92ac3f382ca4933d5f556e78c6&hb=444441f9be866f51920e0ad8ca3909951b4d90c5] - Integrate recover-run command into the run command, auto-detect if the result file was a partial save and then ask if to perform run recovery' [ POSSIBLY DO THE SAME FOR FINISH-RUN] - Multi-threaded downloading of test files - Numerous pts_render improvements [see in-line code comments] ### PTS-GRAPH ### - Improve rendering of large data-sets, e.g. http://openbenchmarking.org/result/1205231-LI-BL460G6BE41 - Rotated text alignment for some PNG graphixs is sometimes off by 90/180 degrees compared to SVG, e.g. http://openbenchmarking.org/s/Compiler - SVG graph improvements ### OPENBENCHMARKING.ORG ### [SUBJECT TO PHORONIX MEDIA NDA] ### NEW TEST PROFILES ### - Python-libmemcached [http://code.google.com/p/python-libmemcached/] - Intel HiBench [https://github.com/intel-hadoop/HiBench] - Hadoop Benchmarks - LATT Latency Tests [git://git.kernel.dk/latt.git] - QMC Beaver [http://qmcbeaver.sourceforge.net/] - Some potential interesting GPGPU tests [http://www.bealto.com/gpu-benchmarks.html] - WebGL / Chrome Test [http://phoronix.com/forums/showthread.php?73167-Some-Benchmarks-to-add-to-PTS-WebGL-and-Google-Chrome] - GtkPerf improvements [http://phoronix.com/forums/showthread.php?73047-gtkperf-I-m-maintaining-feature-requests-new-tests] - Rodinia [https://www.cs.virginia.edu/~skadron/wiki/rodinia/index.php/Main_Page] - Frame latency analysis [http://phoronix.com/forums/showthread.php?74951-Frame-latency-analysis-on-Doom-3&p=295415&posted=1#post295415] - SIPP [http://sipp.sourceforge.net/] - oclGaussCrack [https://hashcat.net/oclGaussCrack/] - ViennaCL [http://viennacl.sourceforge.net/viennacl-benchmarks.html] - Handbrake [http://handbrake.fr/] - libMicro [https://github.com/portante/libMicro] - Expand on OpenCL/CUDA test support within the OpenCL demos, Parboil, etc phoronix-test-suite/documentation/phoronix-test-suite.html0000644000175000017500000024424412223157104024336 0ustar michaelmichaelPhoronix Test Suite v4.8.3 - Test Client Documentation

    Phoronix Test Suite


    1. Getting Started
    2. User Options
    3. Module Options
    4. Installation Instructions
    5. External Dependencies
    6. Configuration
    7. General Information
    8. Virtual Test Suites
    9. Component Testing
    10. Phoromatic
    11. PTS Desktop Live
    12. Development Credits

    Getting Started

    Overview

    The Phoronix Test Suite is the most comprehensive testing and benchmarking platform available for Linux, Solaris, Mac OS X, and BSD operating systems. The Phoronix Test Suite allows for carrying out tests in a fully automated manner from test installation to execution and reporting. All tests are meant to be easily reproducible, easy-to-use, and support fully automated execution. The Phoronix Test Suite is open-source under the GNU GPLv3 license and is developed by Phoronix Media in cooperation with partners. Version 1.0 of the Phoronix Test Suite was publicly released in 2008.

    The Phoronix Test Suite client itself is a test framework for providing seamless execution of test profiles and test suites. There are more than 200 tests available by default, which are transparently available via OpenBenchmarking.org integration. Of these default test profiles there is a range of sub-systems that can be tested and a range of hardware from mobile devices to desktops and worksrtations/servers. New tests can be easily introduced via the Phoronix Test Suite's extensible test architecture, with test profiles consisting of XML files and shell scripts. Test profiles can produce a quantitative result or other qualitative/abstract results like image quality comparisons and pass/fail. Using Phoronix Test Suite modules, other data can also be automatically collected at run-time such as the system power consumption, disk usage, and other software/hardware sensors. Test suites contain references to test profiles to execute as part of a set or can also reference other test suites. Test suites are defined via an XML schema.

    Running the Phoronix Test Suite for the first time can be as simple as issuing a command such as phoronix-test-suite benchmark c-ray, which would proceed to install a simple CPU test, execute the test, and report the results. Along with the results, the system's hardware/software information is collected in a detailed manner, relevant system logs, and other important system attributes such as compiler flags and system state. Users can optionally upload their results to OpenBenchmarking.org for sharing results with others, comparing results against other systems, and to carry out further analysis.

    OpenBenchmarking.org

    OpenBenchmarking.org is an open, collaborative testing platform that makes the Phoronix Test Suite an even more extensible platform for conducting automated tests with complete integration into Phoronix Test Suite test client. OpenBenchmarking.org serves as a repository for storing test profiles, test suites, and result data. Test profiles and suites are stored in the OpenBenchmarking.org cloud to allow for new/updated tests to be seamlessly obtained via the Phoronix Test Suite without needing to manually update the Phoronix Test Suite client. OpenBenchmarking.org also makes it easy to facilitate side-by-side comparisons with any other results stored in the OpenBenchmarking.org cloud. Any Phoronix Test Suite user is permitted to upload their test results, test profiles, and suites to OpenBenchmarking.org.

    When finding a set of results on OpenBenchmarking.org (e.g. an example result file), it's as easy as running the Phoronix Test Suite with that OpenBenchmarking.org ID to perform an automated side-by-side comparison (e.g. phoronix-test-suite benchmark 1203160-BY-NVTEGRA3785).

    Thanks to the wealth of test data (results, system logs, etc) from crowd-sourced benchmarking via the Phoronix Test Suite, a plethora of analytical features are also available from OpenBenchmarking.org.

    Phoromatic

    Phoromatic is a remote management system for the Phoronix Test Suite that allows the automatic scheduling of tests, remote installation of new tests, and the management of multiple test systems all through an intuitive, easy-to-use web interface. Tests can be scheduled to automatically run on a routine basis across multiple test systems. Phoromatic can also interface with revision control systems to offer support for issuing new tests on a context-basis, such as whenever a Git commit has been pushed or new daily image available. The test results are then available from this central, secure location.

    Phoromatic is an add-on to the Phoronix Test Suite that's primarily intended for enterprise users when facilitating tests across a wide-spectrum of hardware within a test lab or when needing to carry out tests on a routine basis.


    User Options

    The following options are currently supported by the Phoronix Test Suite client. A list of available options can also be found by running phoronix-test-suite help.


    Test Installation

    install [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option will install the selected test(s) inside the testing environment directory). The install process from downloading of the test files to the installation is fully automated. The install option needs to be supplied with the test name or suite as an argument. Optionally, a OpenBenchmarking.org ID or the name of a saved results file can be supplied as well and the test(s) to install will automatically be extracted from that information. If the test is already installed and was run by the latest version of the installation process, no action will be taken. Multiple arguments can be supplied to install additional tests at the same time.

    install-dependencies [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option will install the external dependencies needed by the selected test(s) using the distribution's package management system. For example, some tests depend upon GCC for compiling code. If GCC is not detected on the system, the Phoronix Test Suite will attempt to install GCC using the distribution's package management system. If you are running this command as a local user, you may be prompted for the root password while the process is running. For unsupported distributions, the dependency names will be displayed along with common names for the package. The install-dependencies option needs to be supplied with the test name or suite as an argument. When using the install option, the external dependencies are automatically checked.

    make-download-cache

    This option will create a download cache for use by the Phoronix Test Suite.

    remove-installed-test [Test]

    This option will permanently remove a installed test by the Phoronix Test Suite.

    Testing

    auto-compare

    This option will autonomously determine the most relevant test(s) to run for any selected sub-system(s). The tests to run are determined via OpenBenchmarking.org integration with the global results pool. Related test results from OpenBenchmarking.org are also merged to provide a straight-forward and effective means of carrying out a system comparison. If wishing to find comparable results for any particular test profile(s), simply pass the test profile names as additional arguments to this command.

    benchmark [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option will install the selected test(s) (if needed) and will proceed to run the test(s). This option is equivalent to running phoronix-test-suite with the install option followed by the run option. Multiple arguments can be supplied to run additional tests at the same time and save the results into one file.

    finish-run [Test Result]

    This option can be used if a test run had not properly finished running all tests within a saved results file. Using this option when specifying a saved results file where all tests had not completed will attempt to finish testing on the remaining tests where there are missing results.

    run [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option will run the selected test(s).

    run-tests-in-suite

    This option can be used if you wish to run all of the tests found in a supplied suite, but you wish to re-configure each of the test options rather than using the defaults supplied by the suite.

    Batch Testing

    batch-benchmark [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option and its arguments are equivalent to the benchmark option, but the process will be run in the Phoronix Test Suite batch mode.

    batch-install [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    If you wish to run the install process in the Phoronix Test Suite batch mode but do not wish to run any tests at this time. Running the install process in the batch mode will use the default values and not prompt the user of any possible options, to ensure the process is fully automated.

    batch-run [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option and its arguments are equivalent to the run option, but the process will be run in the Phoronix Test Suite batch mode.

    batch-setup

    This option is used to configure the batch mode options for the Phoronix Test Suite, which is subsequently written to the user configuration file. Among the options are whether to automatically upload the test results to OpenBenchmarking.org and prompting for the saved file name.

    default-benchmark [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option will install the selected test(s) (if needed) and will proceed to run the test(s) in the defaults mode. This option is equivalent to running phoronix-test-suite with the install option followed by the default-run option.

    default-run [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option will run the selected test(s). The name of the test or suite must be supplied or the OpenBenchmarking.org ID or saved local file name. Multiple arguments can be supplied to run additional tests at the same time and save the results in a suite-like fashion. Unlike the normal run option, the default-run will not prompt the user to select from the available test options but will instead use the default options as automatically set by pts-core or the test profile. Use batch-run to automatically test all of the available options.

    internal-run [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option and its arguments pre-set the Phoronix Test Suite batch run mode with sane values for carrying out benchmarks in a semi-automated manner and without uploading any of the result data to the public OpenBenchmarking.org.

    OpenBenchmarking.org

    clone-result [OpenBenchmarking ID] ...

    This option will download a local copy of a file that was saved to OpenBenchmarking.org, as long as a valid public ID is supplied. More than one ID can be specified and the results will then be merged.

    list-recommended-tests

    This option will list recommended test profiles for benchmarking sorted by hardware sub-system. The recommended tests are determined via querying OpenBenchmarking.org and determining the most popular tests for a given environment based upon the number of times a test profile has been downloaded, the number of test results available on OpenBenchmarking.org for a given test profile, the age of the test profile, and other weighted factors.

    openbenchmarking-changes

    This option will list recent changes to test profiles of enabled OpenBenchmarking.org repositories.

    openbenchmarking-launcher

    This option is called automatically with the .openbenchmarking MIME file extension support for launching OpenBenchmarking.org operations.

    openbenchmarking-login

    This option is used for controlling your Phoronix Test Suite client options for OpenBechmarking.org and syncing the client to your account.

    openbenchmarking-refresh

    This option is used for refreshing the stored OpenBenchmarking.org repostory information and other data. The Phoronix Test Suite will automatically refresh this data every three days or when other thresholds are exceeded, but this command can be used to manually refresh/updates the data.

    openbenchmarking-repositories

    This option will list the OpenBenchmarking.org repositories currently linked to this Phoronix Test Suite client instance.

    upload-result [Test Result]

    This option is used for uploading a test result to OpenBenchmarking.org.

    upload-test-profile

    This option can be used for uploading a test profile to your account on OpenBenchmarking.org. By uploading your test profile to OpenBenchmarking.org, others are then able to browse and access this test suite for easy distribution in a seamless manner by other Phoronix Test Suite clients.

    upload-test-suite

    This option can be used for uploading a test suite to your account on OpenBenchmarking.org. By uploading your test suite to OpenBenchmarking.org, others are then able to browse and access this test suite for easy distribution.

    System

    detailed-system-info

    Display detailed information about the installed system hardware and software information as detected by the Phoronix Test Suite Phodevi Library.

    diagnostics

    This option will print information that is useful to developers when debugging problems with the Phoronix Test Suite and/or test profiles and test suites.

    interactive

    A simple text-driven interactive interface to the Phoronix Test Suite.

    system-info

    Display the installed system hardware and software information as detected by the Phoronix Test Suite Phodevi Library.

    system-sensors

    Display the installed system hardware and software sensors in real-time as detected by the Phoronix Test Suite Phodevi Library.

    Information

    info [Test | Suite | OpenBenchmarking.org ID | Test Result]

    This option will show details about the supplied test, suite, virtual suite, or result file.

    list-available-suites

    This option will list all test suites that are available from the enabled OpenBenchmarking.org repositories.

    list-available-tests

    This option will list all test profiles that are available from the enabled OpenBenchmarking.org repositories.

    list-available-virtual-suites

    This option will list all available virtual test suites that can be dynamically created based upon the available tests from enabled OpenBenchmarking.org repositories.

    list-installed-dependencies

    This option will list all of the packages / external test dependencies that are already installed on the system that the Phoronix Test Suite may potentially depend upon by test profiles.

    list-installed-suites

    This option will list all suites that are currently installed on the system.

    list-installed-tests

    This option will list all test profiles that are currently installed on the system.

    list-missing-dependencies

    This option will list all of the packages / external test dependencies that are missing from the system that the Phoronix Test Suite may potentially need by select test profiles.

    list-possible-dependencies

    This option will list all of the packages / external test dependencies that are are potentially used by the Phoronix Test Suite.

    list-saved-results

    This option will list all of the saved test results found on the system.

    list-test-usage

    This option will list various details about installed tests and their usage.

    list-unsupported-tests

    This option will list all available test profiles that are available from the enabled OpenBenchmarking.org repositories but are NOT SUPPORTED on the given hardware/software platform. This is mainly a debugging option for those looking for test profiles to potentially port to new platforms, etc.

    Asset Creation

    debug-install [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option is intended for use by test profile writers and is identical to the install option but will yield more information during the run process that can be used to debug issues with a test profile installer or to verify the test profile is functioning correctly.

    debug-run [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option is intended for use by test profile writers and is identical to the <em>run</em> option but will yield more information during the run process that can be used to debug issues with a test profile or to verify the test profile is functioning correctly.

    debug-test-download-links [Test | Suite]

    This option will check all download links within the specified test profile(s) to ensure there are no broken URLs.

    download-test-files [Test | Suite] ...

    This will download the selected test file(s) to the Phoronix Test Suite download cache but will not install the tests.

    force-install [Test | Suite | OpenBenchmarking.org ID | Test Result] ...

    This option will force the installation (or re-installation) of a test or suite. The arguments and process is similar to the install option but even if the test is installed, the entire installation process will automatically be executed. This option is generally used when debugging a test installation problem.

    result-file-to-suite [Test Result]

    This option will guide the user through the process of generating their own test suite, which they can then run, that is based upon an existing test results file.

    validate-result-file

    This option can be used for validating a Phoronix Test Suite result file as being compliant against the OpenBenchmarking.org specification.

    validate-test-profile

    This option can be used for validating a Phoronix Test Suite test profile as being compliant against the OpenBenchmarking.org specification.

    validate-test-suite

    This option can be used for validating a Phoronix Test Suite test suite as being compliant against the OpenBenchmarking.org specification.

    Result Management

    copy-run-in-result-file [Test Result]

    This option is used if you wish to change an existing test run within a saved results file.

    extract-from-result-file [Test Result]

    This option will extract a single set of test results from a saved results file that contains multiple test results that have been merged. The user is the prompted to specify a new result file name and select which result identifier to extract.

    merge-results [Test Result] ...

    This option will manually merge multiple sets of test results generated by the Phoronix Test Suite.

    refresh-graphs [Test Result]

    This option will re-render and save all result graphs within a saved file. This option can be used when making modifications to the graphing code or its color/option configuration file and testing the changes.

    remove-from-result-file [Test Result]

    This option is used if there is a set of test results you wish to remove/delete from a saved results file. The user must specify a saved results file and then they will be prompted to select the results identifier associated with the results they wish to remove.

    remove-result [Test Result]

    This option will permanently remove the saved file set that is set as the first argument.

    rename-identifier-in-result-file [Test Result]

    This option is used if you wish to change the name of the identifier in a test results file that is shown in the Phoronix Test Suite Results Viewer and the contained graphs.

    reorder-result-file [Test Result]

    This option is used if you wish to change the order in which test results are shown in the Phoronix Test Suite Results Viewer and the contained graphs. The user must specify a saved results file and then they will be prompted to select the results identifiers one at a time in the order they would like them to be displayed from left to right.

    result-file-to-csv [Test Result]

    This option will read a saved test results file and output the system hardware and software information along with the results to a CSV output. The CSV (Comma Separated Values) output can then be loaded into a spreadsheet for easy viewing.

    result-file-to-pdf [Test Result]

    This option will read a saved test results file and output the system hardware and software information along with the results to a PDF file.

    result-file-to-text [Test Result]

    This option will read a saved test results file and output the system hardware and software information to the terminal. The test results are also outputted.

    show-result [Test Result]

    Open up the test results in the Phoronix Test Suite Result Viewer or on OpenBenchmarking.org.

    Result Analytics

    analyze-all-runs [Test Result]

    This option will generate a candlestick graph showing the distribution of results from all trial runs. The candlestick graph is similar to the Japanese candlestick charts used by the financial industry, except instead of representing stock data it is numerical result data from all trial runs.\n\nThe tip of the upper-wick represents the highest value of the test runs with the tip of the lower-wick representing the lowest value of all test runs. The upper-edge of the candle body represents the first or last run value and the lower-edge represents the first or last run value. Lastly, if the last run value is less than the first run value, the candle body is the same color as the graph background, otherwise the last run value is greater.

    analyze-batch [Test Result]

    This option will analyze a batch results file and plot out the performance impact from the different options onto a line graph (i.e. to see the impact that changing the video resolution has on the system's performance).

    analyze-image-delta [Test Result]

    This option will analyze a test result file if it contains any test results that produced an image quality comparison (IQC) and will render image deltas illustrating the difference between images from two test results.

    Other

    build-suite

    This option will guide the user through the process of generating their own test suite, which they can then run. Optionally, passed as arguments can be the test(s) or suite(s) to add to the suite to be created, instead of being prompted through the process.

    debug-self-test

    This option is used during the development of the Phoronix Test Suite software for testing of internal interfaces, commands, and other common code-paths. The produced numbers should only be comparable for the same version of the Phoronix Test Suite, on the same hardware/software system, conducted on the same day of testing. This isn't intended as any scientific benchmark but simply to stress common PHP code-paths and looking for hot areas to optimize, etc.

    help

    This option will display the list of available Phoronix Test Suite commands.

    network-setup

    This option allows the user to configure how the Phoronix Test Suite connects to OpenBenchmarking.org and other web-services. Connecting through an HTTP proxy can be configured through this option.

    rebuild-composite-xml [Test Result]

    This option can be used to rebuild your composite XML file in the event that the main result file was corrupted and the test-X.xml files are still present in the result file directory.

    user-config-reset

    This option can be used for resetting the Phoronix Test Suite user configuration file to its default state.

    user-config-set

    This option can be used for setting an XML value in the Phoronix Test Suite user configuration file.

    version

    This option will display the Phoronix Test Suite client version.

    Modules

    list-modules

    This option will list all of the available Phoronix Test Suite modules on this system.

    module-info [Phoronix Test Suite Module]

    This option will show detailed information on a Phoronix Test Suite module such as the version, developer, and a description of its purpose.

    module-setup [Phoronix Test Suite Module]

    This option will allow you to configure all available end-user options for a Phoronix Test Suite module. These options are then stored within the user's configuration file. Not all modules may have options that can be configured by the end-user.

    test-module [Phoronix Test Suite Module]

    This option can be used for debugging a Phoronix Test Suite module.


    Module Options

    The following list is the modules included with the Phoronix Test Suite that are intended to extend the functionality of pts-core. Some of these options have commands that can be run directly in a similiar manner to the other Phoronix Test Suite user commands. Some modules are just meant to be loaded directly by adding the module name to the LoadModules tag in ~/.phoronix-test-suite/user-config.xml or via the PTS_MODULES environmental variable. A list of available modules is also available by running phoronix-test-suite list-modules.


    Dummy Module

    This is a simple module intended for developers to just demonstrate some of the module functions.

    phoronix-test-suite dummy_module.dummy-command

    OpenBenchmarking.org Ekofisk

    The Ekofisk client is used for connecting to OpenBenchmarking.org to facilitate the automatic running of tests, generally across multiple test nodes in a routine manner.

    phoronix-test-suite ekofisk.start

    phoronix-test-suite ekofisk.user-system-return

    Graphics Event Checker

    This module checks a number of events prior to and and after running a test to make sure the graphics sub-system was not put in a sour or unintended state by the application. For instance, it makes sure syncing to vBlank is not forced through the driver and that a graphics test has not left the display in an unintended mode.

    Graphics Override

    This module allows you to override some graphics rendering settings for the ATI and NVIDIA drivers while running the Phoronix Test Suite.

    This module utilizes the following environmental variables: FORCE_AA, FORCE_AF.

    MATISK

    My Automated Test Infrastructure Setup Kit

    phoronix-test-suite matisk.run

    phoronix-test-suite matisk.template

    Phoromatic Client

    The Phoromatic client is used for connecting to a Phoromatic server (Phoromatic.com or a locally run server) to facilitate the automatic running of tests, generally across multiple test nodes in a routine manner. For more details visit http://www.phoromatic.com/

    phoronix-test-suite phoromatic.start

    phoronix-test-suite phoromatic.user-system-return

    phoronix-test-suite phoromatic.upload-results

    phoronix-test-suite phoromatic.clone-results

    phoronix-test-suite phoromatic.system-schedule

    phoronix-test-suite phoromatic.system-schedule-today

    phoronix-test-suite phoromatic.send-message

    Result Notifier

    A notification module.

    System Monitor

    This module contains sensor monitoring support.

    This module utilizes the following environmental variables: MONITOR, PERFORMANCE_PER_WATT.

    Timed Screenshot

    This is a module that will take a screenshot of the system at a pre-defined interval. ImageMagick must be installed onto the system prior to using this module.

    This module utilizes the following environmental variables: SCREENSHOT_INTERVAL.

    Toggle Screensaver

    This module toggles the system's screensaver while the Phoronix Test Suite is running. At this time, the GNOME and KDE screensavers are supported.

    This module utilizes the following environmental variables: HALT_SCREENSAVER.

    Update Checker

    This module checks to see if the Phoronix Test Suite -- and its tests and suites -- are up to date.


    Installation Instructions

    Setup Overview

    The Phoronix Test Suite supports Linux, Apple Mac OS X, Microsoft Windows, Solaris, Hurd, BSD, and other operating system environments. The only Linux distribution-specific code deals with the external dependencies support feature that are set by individual test profiles. If you are not running one of the supported Linux distributions, Solaris, BSD, or Mac OS X, you may need to install a package manually (as instructed by the Phoronix Test Suite) in order for a test to run. An example of an external dependency would be GCC and the OpenGL Utility Toolkit being needed for test profiles that build an OpenGL benchmark from source-code.

    Among the distributions where the Phoronix Test Suite has been officially tested include Ubuntu, Fedora, Mandriva / Mageia, Gentoo, PCLinuxOS, Arch Linux, Pardus, OpenSuSE, Optware, webOS, Zenwalk, CentOS, Red Hat Enterprise Linux, Oracle Linux, Scientific Linux, Debian, Mint, MEPIS, and Amazon Linux EC2.

    Among the tested BSD distributions are FreeBSD, PC-BSD, NetBSD, OpenBSD, Debian GNU/kFreeBSD, and DragonflyBSD. Tested Solaris distributions include OpenSolaris, Solaris Express 11, Oracle Solaris 11, OpenIndiana, Illumos, and Nexenta.

    Dependencies

    The only required dependency for the Phoronix Test Suite is PHP 5.2 or newer. On Linux distributions, the needed package is commonly called php5-cli or php-cli or php. It is important to note that only PHP for the command-line is needed and not a web server (Apache) or other packages commonly associated with PHP and its usage by web-sites. The PHP5 version required is PHP 5.2+ and can also be found at www.php.net.

    As part of the PHP requirement, the following PHP extensions are required and/or highly recommended in order to take advantage of the Phoronix Test Suite capabilities:

    • PHP DOM is needed for XML operations and must be installed for the Phoronix Test Suite to function.
    • PHP ZIP is needed for file compression and decompression and specifically dealing with test profiles and suites obtained via OpenBenchmarking.org or when uploading such tests and suites.
    • PHP OpenSSL is used for enabling HTTPS communication with Phoronix Test Suite / OpenBenchmarking.org servers.
    • PHP GD is highly recommended for rendering of test data to JPEG and PNG image formats and is selectively used in other image operations.
    • PHP Zlib is highly recommended for greater data compression when dealing with remote OpenBenchmarking.org assets.
    • PHP PCNTL is used for multi-threaded system sensor monitoring support during the testing process and other threaded tasks by the Phoronix Test Suite module framework.
    • PHP POSIX is used for reliably obtaining more system information in an efficient manner.
    • PHP CURL is supported as an alternative networking library for improved network performance in downloading test files and other operations.
    • PHP FPDF is used to generate PDF reports of test data.

    Without all of these extensions, some capabilities of the Phoronix Test Suite will not be available. Many of these packages are enabled by default and do not require any additional installation steps on most Linux distributions, otherwise they are often found in the package vendor's repository.

    Notes

    General

    You may need to modify the php.ini file on your system in order to support uploading results to OpenBenchmarking.org or logging into your OpenBenchmarking.org account. The allow_url_fopen, file_uploads, and allow_url_include options must be set to true in the PHP configuration. See additional information in this Phoronix Forums support thread.

    Major updates to the Phoronix Test Suite are released on a quarterly basis. The latest stable and development versions of the Phoronix Test Suite are available at Phoronix-Test-Suite.com. The Git repository where the latest Phoronix Test Suite code is provided is hosted at Phorogit.com and can be cloned/pulled from the http://www.phorogit.com/repo/phoronix-test-suite.git repository. The latest upstream development code is housed in the master tree while older Phoronix Test Suite releases are available in their respective Git branches based upon the release's code-name.

    If building the PHP package from upstream sources, it should just be a matter of running ./configure with the --enable-zip flag (all other requirements should be apart of the stock PHP configuration) to satisfy the PHP needs of the Phoronix Test Suite.

    File Structure

    If manually changing the location of the phoronix-test-suite launcher file, the PTS_USER_PATH environment variable must be adjusted inside the file to reflect the absolute location that leads to the root directory of the pts and pts-core folders. The pts-core directory contains the "engine" of the Phoronix Test Suite.

    Running Locally

    The Phoronix Test Suite can be simply extracted from the downloaded .tar.gz or .zip file or it can also be installed system-wide. If you just wish to run the Phoronix Test Suite without installing it, open a terminal and run ./phoronix-test-suite <options> from the same directory.

    Generic Installation

    Running install-sh from the root directory of the Phoronix Test Suite will install the software for system-wide access. By default the phoronix-test-suite executable is in /usr/bin/, the Phoronix Test Suite files in /usr/share/phoronix-test-suite/, and the documentation in /usr/share/doc/phoronix-test-suite/. Root access is required. The default installation prefix is /usr/ but can be adjusted as the first argument (example: install-sh /home/user/ to install the Phoronix Test Suite in your home directory).

    Debian/Ubuntu Installation

    Debian/Ubuntu users are able to follow the Generic Installation instructions or can obtain a Debian Package from the Phoronix Test Suite web-site. The package contains the phoronix-test-suite executable in /usr/bin/, the Phoronix Test Suite files in /usr/share/phoronix-test-suite/, and the documentation in /usr/share/doc/phoronix-test-suite/.

    A phoronix-test-suite package can also be found in the official Ubuntu universe repository beginning with the Ubuntu 9.04 (Jaunty) release, but it may be out of date compared to the latest upstream version.

    Fedora / Red Hat Installation

    The Phoronix Test Suite can be installed on Fedora, Red Hat Enterprise Linux, and CentOS systems using the generic installation method. Alternatively, a phoronix-test-suite package is available in recent versions of the Fedora repository and in the EPEL (Extra Packages for Enterprise Linux) repository for Red Hat Enterprise Linux. At this time, however, the Fedora-supplied package is vastly out of date.

    Gentoo Installation

    Gentoo ebuild's for the Phoronix Test Suite have been created by users and can be currently found in the Gentoo BugZilla.

    Mandriva Installation

    Phoronix Test Suite packages are available through Mandriva Cooker starting with the Mandriva Linux 2009 release.

    OpenSolaris Installation

    The Phoronix Test Suite core (pts-core) is supported on Solaris and OpenSolaris platforms, but some features may not fully function. Additionally, the PTS External Dependencies feature is supported on OpenSolaris using IPS (the Image Packaging System). However, not all test profiles are supported on Solaris / OpenSolaris, and it may be in violation of your end-user agreement to perform such benchmarks on the Sun Solaris operating system. Using the OpenSolaris Image Packaging System, installing SUNWphp524 will provide PHP, PHP GD, and related dependencies. The Phoronix Test Suite has also been tested on Oracle Solaris 11 Express, OpenIndiana, StormOS, and Nexenta Core Platform.

    BSD Installation

    The Phoronix Test Suite also supports *BSD operating systems. However, like the Solaris support, not all test profiles are compatible with BSD operating systems, but pts-core has been tested against FreeBSD 7.x/8.x/9.x, NetBSD, PC-BSD 7/8/9, DragonFlyBSD 3.0/3.2/3.4, and OpenBSD 4.4/4.6. The Phoronix Test Suite will also work with Debian GNU/kFreeBSD.

    For DragonFlyBSD, it's a matter of just using pkg_radd with php5, php5-json, php5-dom, and php5-zip or pkgsrc. Under FreeBSD/PC-BSD, PHP can be obtained from the php5 and php5-extensions Ports collection.

    Mac OS X Installation

    The Phoronix Test Suite is fully supported on Apple's Mac OS X operating system as of Mac OS X 10.5 with improved support under Mac OS X 10.6. PHP ships with Mac OS X by default so it's simply a matter of downloading the Phoronix Test Suite package, extracting it, and running the executable. For tests that rely upon a compiler, Apple's XCode with GCC and LLVM can be utilized.

    Windows Installation

    The Phoronix Test Suite support on Windows is in development and will function just fine, but is not yet feature complete compared to the other operating systems support. At this time the Phoronix Test Suite client is dependent upon PHP being installed to C:\Program Files (x86)\PHP\php. The Phoronix Test Suite also uses CPU-Z for much of the hardware detection support on Windows and is dependent upon CPU-Z being installed to C:\Program Files\CPUID\CPU-Z\cpuz.exe if you wish to utilize this hardware reporting feature. In terms of the Microsoft Windows support, right now the Phoronix Test Suite is developed and solely tested against Microsoft Windows 7 x64 and Microsoft Windows 8 x64.

    Facebook HipHop

    The Phoronix Test Suite can use Facebook's HopHop HHVM virtual machine as an alternative to the de facto PHP implementation. The Phoronix Test Suite has been tested against HHVM 2.0. If HHVM is present on the system but not PHP, it will automatically be used by the Phoronix Test Suite. Alternatively, the PHP_BIN environment variable can be set to point to an alternative hhvm binary.

    The Phoronix Test Suite also supports the older version of Facebook HipHop that serves as a PHP to C++ translator and compiler with GCC. This support though is primitive and not officially supported. To compile the Phoronix Test Suite using HipHop/GCC, run find . -name "*.php" > files.list && hphp --input-list=files.list -k 1 --log=3 --include-path="." --cluster-count=50 -v "AllDynamic=true" -v "AllVolatile=true" from the root phoronix-test-suite/ directory. It can then be executed in the form of /tmp/hphp_XXX/program -f pts-core/phoronix-test-suite.php system-info.


    External Dependencies

    The Phoronix Test Suite has a feature known as "External Dependencies" where the Phoronix Test Suite can attempt to automatically install some of the test-specific dependencies on supported distributions. If running on a distribution where there is currently no External Dependencies profile, the needed package name(s) are listed for manual installation.

    Below are a list of the operating systems that currently have external dependencies support within the Phoronix Test Suite for the automatic installation of needed test files.


    • Amazon
    • Angstrom
    • Arch Linux
    • CentOS
    • ClearOS
    • ClearOS Core Server
    • Debian
    • DragonFlyBSD
    • Fedora
    • Fluxbuntu
    • FreeBSD
    • GNU KFreeBSD
    • Gentoo
    • Goobuntu
    • HP
    • Joli Cloud
    • Linaro
    • Linux Mint
    • MEPIS
    • Mac OS X
    • MacPorts
    • Mageia
    • Mandriva
    • MeeGo
    • Moblin
    • Mythbuntu
    • NetBSD
    • Nexenta Core
    • OLPC
    • OpenIndiana
    • OpenMandriva
    • OpenSolaris
    • OpenSuSE
    • Optware
    • Oracle Server
    • PCLinuxOS
    • PTS Desktop Live
    • PTS Linux Live
    • Palm
    • Pardus Linux
    • Red Hat Enterprise
    • Red Hat Enterprise Server
    • SUSE
    • SUSE Linux
    • Scientific
    • ScientificSL
    • Ubuntu
    • Zenwalk
    • gNewSense

    • Configuration

      User Files & Folders

      ~/.phoronix-test-suite/user-config.xml

      This is a per-user configuration file. Among the information stored here is the test options, locations for storing files, and batch mode options. This file is formatted in XML.

      ~/.phoronix-test-suite/graph-config.json

      This is a per-user configuration file for storing graph attributes. The adjustable options include HTML hex color codes for different areas of the graph, dimensions of the graph, and font sizes. This file is formatted in JSON.

      ~/.phoronix-test-suite/download-cache/

      This directory contains test packages that have been downloaded for test profiles. For more information on the download cache.

      ~/.phoronix-test-suite/installed-tests/

      This directory is where tests are installed by default. Each test has its own directory within a sub-directory of installed-tests/ based upon its OpenBenchmarking.org repository. In the test's folder is a pts-install.xml file used for managing the installation.

      ~/.phoronix-test-suite/test-results/

      This directory is where tests results are saved by default. Each saved file has its own directory. In the saved directory is then a composite.xml file containing the useful results while in the test-X.xml files are back-ups of the results.

      ~/.phoronix-test-suite/modules-data/

      This is the directory where any Phoronix Test Suite modules should save any files to, within a sub-directory of the module's name. The module configuration settings are also stored within this directory.

      ~/.phoronix-test-suite/test-profiles/

      This is the directory where test profiles are stored.

      ~/.phoronix-test-suite/test-suites/

      This is the directory where test suites are stored.

      Environment Variables

      TEST_RESULTS_NAME

      When this variable is set, the value will be used as the name for automatically saving the test results.

      TEST_RESULTS_IDENTIFIER

      When this variable is set, the value will be used as the test identifier when automatically saving the test results.

      TEST_RESULTS_DESCRIPTION

      When this variable is set, the value will be used as the test results description when saving the test results.

      PRESET_OPTIONS

      For setting any test option(s) from an environment variable rather than being prompted for the options when running a test. Example: PRESET_OPTIONS="stream.run-type=Add" ./phoronix-test-suite benchmark stream

      SKIP_TESTS

      If there are any test(s) to exempt from the testing process, specify them in this variable. Multiple tests can be waived by delimiting each test identifier by a comma. A test hardware type (i.e. Graphics) can also be supplied for skipping a range of tests.

      ONLY_TEST_TYPES

      If you are running a set of benchmarks (namely a result file) but wish to skip some of the tests that don't belong to a certain test type group, you can set the hardware types to test via this environment variable. E.g. setting ONLY_TEST_TYPE=Graphics will skip all test profiles to run that are not of the graphics test group. Multiple types should be delimited by a comma.

      PTS_MODULE_SETUP

      This variable can be used to load Phoronix Test Suite module settings automatically when using the module-setup option. An example would be: PTS_MODULE_SETUP="phoromatic.remote_host=http://www.phoromatic.com/; phoromatic.remote_account=123456; phoromatic.remote_verifier=ABCD" phoronix-test-suite module-setup phoromatic.

      PTS_MODULES

      If there are any Phoronix Test Suite modules to additionally load, they can be specified here. Multiple modules can be supplied by delimiting them with a comma. The more appropriate way of loading Phoronix Test Suite modules for longer periods of time is by using the ~/.phoronix-test-suite/user-config.xml configuration.

      NO_PHODEVI_CACHE

      This is a debugging option to disable the Phodevi cache from being loaded of cached software/hardware information. Instead, all software/hardware will be polled from the Phodevi library without caching.

      EXTERNAL_PHODEVI_CACHE

      This option can be used for loading an external Phodevi cache. Such as loading the native hardware/software information from within a Windows Wine client from a native system host.

      PTS_DISPLAY_MODE

      If you wish to load a non-default display mode for a single instance, specify the mode in this variable.

      TOTAL_LOOP_TIME

      When running any test(s), if you would like the test(s) to continue running as a loop until a certain time has been reached, this variable can be used. The value should be the number of minutes to run the testing process before the loop is ended.

      TOTAL_LOOP_COUNT

      When running any test(s), if you would like the test(s) to continue running for a number of times, this variable can be used. The value should be the number of times to loop the testing process before ending.

      FORCE_TIMES_TO_RUN

      If you wish to override the number of times to run each test -- rather than the Phoronix Test Suite using the number of times specified in each test profile -- this variable can be used.

      FORCE_MIN_TIMES_TO_RUN

      This is similar to the FORCE_TIMES_TO_RUN option but will only be used if the test profile's run count is less than this defined value.

      NO_FILE_HASH_CHECKS

      To disable MD5/SHA256 check-sums from being checked when downloading test files, set this variable to 1. This variable used to be known as NO_MD5_CHECKS, which is still honored but was changed to NO_FILE_HASH_CHECKS to reflect other kind of file hash sum checks.

      PTS_DOWNLOAD_CACHE

      While non-standard Phoronix Test Suite download caches can be specified within the user-config.xml file, an additional directory to look for potential Phoronix Test Suite download files can be specified by this variable.

      GRAPH_HIGHLIGHT

      If this variable is set with a valid test identifer from a result file whether you are using the refresh-graphs command or any other related to the rendering of test results on a bar graph, the specified test identifier's result will be highlighted in a different color than the other rendered test results. Multiple identifiers can be specified when delimited by a comma.

      VIDEO_MEMORY

      If Phodevi fails to detect the system's video memory capacity or is incorrectly detected, the video memory capacity (in MB) can be specified by this variable.

      OVERRIDE_VIDEO_MODES

      If Phodevi fails to detect all of the system's monitor video modes or a separate set of modes would be preferred, the modes can be specified in this variable. Example: OVERRIDE_VIDEO_MODES=800x600,1024x768,1280x1024 phoronix-test-suite benchmark nexuiz.

      SKIP_TEST_SUPPORT_CHECKS

      If this environment variable is set, it will not honor the support checks made by individual test profiles. I.e. test profiles that would normally be considered un-supported on a given platform are attempted to install and run regardless.

      SKIP_ALL_TEST_SUPPORT_CHECKS

      If this environment variable is set, all tests will be permitted on the client for execution. SKIP_ALL_TEST_SUPPORT_CHECKS is more liberal than SKIP_TEST_SUPPORT_CHECKS in letting disk tests run on RAM-based file-systems, attempt to run 2D/3D tests on VESA display drivers, and other special cases.

      DEFAULT_VIDEO_MODE

      If Phodevi fails to detect the system's monitor standard / default resolution, the mode can be specified in this variable. Example: DEFAULT_VIDEO_MODE=1680x1050 phoronix-test-suite benchmark nexuiz.

      SKIP_EXTERNAL_DEPENDENCIES

      To skip the Phoronix Test Suite external dependency checking/installation when installing a test, set this environment variable to 1. If wishing to skip only certain external dependencies, set this variable's value to the name of the external dependencies (the generic dependency names used by the Phoronix Test Suite) to not install. Multiple dependencies to skip can be delimited by a comma.


      General Information

      Frequently Asked Questions

      Q: May I use the Phoronix Test Suite when running benchmarks for my own publication or blog? Are there any publishing restrictions?

      A: Anyone is more than welcome to use the Phoronix Test Suite for their own publication or purpose. While the Phoronix Test Suite came out of our internal test tools for carrying out Linux hardware reviews at Phoronix.com, we invite other hardware review web-sites, technology journals, and independent publications to use our software too. While not required, we would just kindly ask that you mention in your review/article that the Phoronix Test Suite was used for carrying out your testing, and ideally to link to www.phoronix-test-suite.com so that your readers will know where to obtain the software if they are interested in running the tests. You are also more than welcome to upload your results to OpenBenchmarking.org so that others may compare their results against yours in an easy manner.

      We also try to make the Phoronix Test Suite easy-to-use by independent publications. For example, if you would like to watermark your web-site's URL into the graphs containing your test results, that can be easily modified in ~/.phoronix-test-suite/graph-config.json. The colors and other graph settings are also stored in this XML file. If you are a publication and run into any issues with the Phoronix Test Suite or have a feature request, please let us know.

      A partial list of other publications using the Phoronix Test Suite can be found in this forum thread.

      Q: Why does the Phoronix Test Suite not use my distribution's package management system for acquiring all needed packages?

      A: The tests themselves are generally downloaded from source and built locally on the machine, rather than fetching any distribution-specific packages. This is done to ensure more comparable results across operating systems / releases, etc. The distribution packager could be applying a number of unknown patches to the software, building the software with unique build options, or making other changes to the software that could skew the results.

      Q: Besides being a developer, documentation writer, or having any other unique technical abilities, how else can I contribute to the Phoronix Test Suite?

      A: Independent code contributions are very welcome as well as creating your own test profiles and suites. We also appreciate any feedback, comments, or other ideas either by emailing us, posting on the forums, or sending a message to the mailing list. You can also see this (outdated) forum thread.

      Q: Do you offer technical support for the Phoronix Test Suite

      A: Paid, professional support is available and is done via our commercial services. We also offer Phoromatic licenses for use within a corporate intranet and other custom services. Free, community support is offered via our mailing list, IRC channel (#phoronix on FreeNode.net, and the Phoronix Forums.

      Q: May I put the Phoronix Test Suite logo on my company's web-site or on my product packaging?

      A: Contact us for licensing information and details regarding the Phoronix Certification & Qualification Suite.

      Q: How often is the Phoronix Test Suite updated?

      A: We provide major updates on a quarterly basis with an occasional point release to fix outstanding bugs or address other issues. The latest work going into the Phoronix Test Suite is accessible via our Git repository at Phorogit.com.

      Tips & Tricks

      General

      - The desktop's screensaver will automatically be shutdown when a test is running and will be restored to its previous state upon the test's completion. This is supported for GNOME, KDE, and other XDG-supportive desktop environments.

      - If you have many computers you wish to benchmark, once all of your tests have been downloaded, run phoronix-test-suite make-download-cache to generate a copy of these files at ~/.phoronix-test-suite/download-cache/. A download cache is used for conserving time and bandwidth by eliminating the need for the Phoronix Test Suite to download files that have already been downloaded once. Copy this folder to the other systems or copy it to a DVD or USB hard drive, connect it to the next test system, and the Phoronix Test Suite will automatically use this local download cache. Or store these files on a local HTTP/FTP server and then update your ~/.phoronix-test-suite/user-config.xml file to reflect the location of this download cache directory.

      Running

      - When running a test in batch mode (through the use of the batch-run or batch-benchmark options) that normally has end-user options (such as the sub-test to run or resolution), the Phoronix Test Suite will run the test with each unique combination of options possible, if configured appropriately.

      - When running a test where you are prompted to enter any test options, multiple selections can be performed -- which will result in multiple test runs for each combination of the selected option(s) -- by separating each intended test option / number with a comma.

      - When being prompted for the test identifier or the file name for saving the results, several user variables are supported. These include $VIDEO_RESOLUTION, $VIDEO_CARD, $OPERATING_SYSTEM, $PROCESSOR, $MOTHERBOARD, $CHIPSET, and $KERNEL_VERSION. If any of these variables are entered, the Phoronix Test Suite will replace them with their respective values before saving the results.

      - If RemoveDownloadFiles is set to TRUE within the user-config.xml file, once a test has been installed the originally downloaded files for that test will be automatically removed. This conserves disk space but will cause these files to be re-downloaded the next time the test needs to be re-installed. This will also not back up the downloaded files to the Phoronix Test Suite download cache. Enabling this option is just recommended for users with very limited disk space.

      - If the amount of video memory for your graphics card is incorrectly reported by the Phoronix Test Suite (you can check by running phoronix-test-suite diagnostics), you can use the VIDEO_MEMORY= environment variable for overriding the video memory capacity (in Megabytes) used by the Phoronix Test Suite.

      - If the DISPLAY environment variable is not set or NO_GRAPHICS_TESTS environment variable is set, tests of type Graphics will not be run. Likewise, if NO_SYSTEM_TESTS environment variable is set, tests of type System will not run. This applies to all test types where NO_<TEST TYPE>_TESTS is set.

      - If while running multiple tests you want to quit the testing prematurely, in a new terminal window type touch ~/.phoronix-test-suite/halt-testing. All results for tests that had already run will be saved (permitting you opted to save the results), except for the test currently being run.

      - If you wish to stop the current test run prematurely but continue the testing process, in a new terminal window type touch ~/.phoronix-test-suite/skip-test.

      - If you want the specified test(s) to run in a loop for a set period of time, use the TOTAL_LOOP_TIME environment variable. For instance, running TOTAL_LOOP_TIME=120 phoronix-test-suite benchmark ffmpeg would keep running the ffmpeg test profile for 120 minutes.

      - If you want the specified test(s) to run in a loop for a set number of times, use the TOTAL_LOOP_COUNT environment variable. For instance, running TOTAL_LOOP_COUNT=3 phoronix-test-suite benchmark ffmpeg would keep running the ffmpeg test profile three times.

      - When any tests are being installed and when tests are being run, a lock is created in the system's temporary directory with the name phoronix-test-suite.active (i.e. /tmp/phoronix-test-suite.active) and is removed upon completion. Thus if you have any system scripts that you wish to run when tests are not running or being installed as to not impact the results, one simple way to handle this is by having the script check for the existence of this lock.

      Configuration

      - The user configuration options for the Phoronix Test Suite are stored in ~/.phoronix-test-suite/user-config.xml. The batch mode options are also stored within this file and those can be adjusted by running phoronix-test-suite batch-setup.

      - The colors, size, and other attributes for the graphs found within the Phoronix Test Suite Results Viewer can be modified via the file ~/.phoronix-test-suite/graph-config.json.

      Test / Suite Writing

      - The Phoronix Test Suite recursively determines tests/suites and allows a suite to call another suite.

      Module Writing

      - By writing a Phoronix Test Suite module, you can easily extend the functionality of the Phoronix Test Suite. Some examples are being able to email the results upon completion, controlling the system's screensaver, updating a text LCD panel with the current test status, etc.


      Virtual Test Suites

      Virtual test suites are not like a traditional test suite defined by the XML suite specification. Virtual test suites are dynamically generated in real-time by the Phoronix Test Suite client based upon the specified test critera. Virtual test suites can automatically consist of all test profiles that are compatible with a particular operating system or test profiles that meet other critera. When running a virtual suite, the OpenBenchmarking.org repository of the test profiles to use for generating the dynamic suite must be prefixed.

      Virtual test suites can be installed and run just like a normal XML test suite and shares nearly all of the same capabilities. However, when running a virtual suite, the user will be prompted to input any user-configuration options for needed test profiles just as they would need to do if running the test individually. When running a virtual suite, the user also has the ability to select individual tests within the suite to run or to run all of the contained test profiles. Virtual test suites are also only supported for an OpenBenchmarking.org repository if there is no test profile or test suite of the same name in the repository. Below is a list of common virtual test suites for the main Phoronix Test Suite repository, but the dynamic list of available virtual test suites based upon the enabled repositories is available by running phoronix-test-suite list-available-virtual-suites.


      All PTS Tests pts/all

      This is a collection of all test profiles found within the specified OpenBenchmarking.org repository.

      Installed Tests pts/installed

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository that are already installed on the system under test.

      Linux Operating System Tests pts/linux

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being compatible with the Linux Operating System.

      Solaris Operating System Tests pts/solaris

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being compatible with the Solaris Operating System.

      BSD Operating System Tests pts/bsd

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being compatible with the BSD Operating System.

      MacOSX Operating System Tests pts/macosx

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being compatible with the MacOSX Operating System.

      Windows Operating System Tests pts/windows

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being compatible with the Windows Operating System.

      Hurd Operating System Tests pts/hurd

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being compatible with the Hurd Operating System.

      System Subsystem Tests pts/system

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a test of the System sub-system.

      Processor Subsystem Tests pts/processor

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a test of the Processor sub-system.

      Graphics Subsystem Tests pts/graphics

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a test of the Graphics sub-system.

      Other Subsystem Tests pts/other

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a test of the Other sub-system.

      Utility Tests pts/utility

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a Utility software test.

      Simulator Tests pts/simulator

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a Simulator software test.

      Scientific Tests pts/scientific

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a Scientific software test.

      Benchmark Tests pts/benchmark

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a Benchmark software test.

      Application Tests pts/application

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a Application software test.

      Game Tests pts/game

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified as being a Game software test.

      Smp Tests pts/smp

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified via an internal tag as testing smp.

      Python Tests pts/python

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified via an internal tag as testing python.

      Mpi Tests pts/mpi

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified via an internal tag as testing mpi.

      Openmp Tests pts/openmp

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified via an internal tag as testing openmp.

      Cuda Tests pts/cuda

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified via an internal tag as testing cuda.

      Vdpau Tests pts/vdpau

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified via an internal tag as testing vdpau.

      Video Tests pts/video

      This is a collection of test profiles found within the specified OpenBenchmarking.org repository where the test profile is specified via an internal tag as testing video.


      Component Testing

      Compiler Testing & Masking

      A majority of the test profiles provided by OpenBenchmarking.org to the Phoronix Test Suite are source-based tests. Relying upon the upstream source-code for each program under test allows for the tests to be easily brought to new platforms and architectures, avoids any out-of-tree / non-default packaging differences by different distributions and operating systems, and to allow the Phoronix Test Suite user to easily test new compilers and/or compiler options. For the source-based tests, the Phoronix Test Suite relies upon a compiler (e.g. GCC, LLVM/Clang, Sun Studio, Open64, et al) being present on the system under test. The Phoronix Test Suite does respect CC/CXX environment variables and test profiles are expected to honor CFLAGS/CXXFLAGS and other compiler settings.

      As of Phoronix Test Suite 3.8, a compiler masking method is utilized for logging compiler options and other settings with each test profile installation. Prior to installing an open-source test, the Phoronix Test Suite determines the intended compiler to be used based upon the pre-set environment variables or the pre-set compiler(s) within the PATH environment variable. The Phoronix Test Suite then masks the compiler to ensure that any options/flags submitted to the compiler are first passed through pts-core so that they can be logged for later use, then is linked to the original, intended compiler. Additionally, other compiler binary names of the same type are blacklisted to prevent their un-intended use (i.e. if a test profile has hard-coded gcc in its build script, but clang is set as the compiler via CC, a sym-link will automatically be created from gcc to the masked clang for the duration of its test installation).

      The logged compiler data is then used by the Phoronix Test Suite following the test execution process for automated result analysis. If there is a detected change in compiler settings, the differences are automatically reported to the test result graphs. Additionally, key compiler information (e.g. the compiler optimization level and key libraries that were linked at compile-time) is reported as a footnote on result graphs. The Phoronix Test Suite handles all of this in a fully automated manner; test profiles require no changes to take advantage of these compiler-reporting capabilities.

      Separately, the Phoronix Test Suite attempts to automatically log the system compiler's build configuration (i.e. GCC's gcc -v "Configured with") output. If the Phoronix Test Suite detects there is a compiler build configuration change between test runs in a result file, it will report each compiler's build configuration to the system information table within the results viewer. Reported to the table is a reduced view of the build configuration options, with less relevant items being stripped away from this view to reduce verbosity. Upon clicking the text, the raw compiler information output can be viewed in full.

      Disk / File-System Testing

      By default tests are installed to ~/.phoronix-test-suite/installed-tests/. However, the location can be updated from ~/.phoronix-test-suite/user-config.xml or dynamically via the PTS_TEST_INSTALL_ROOT_PATH environment variable.

      When any disk tests are executed, the Phoronix Test Suite will attempt to log the mount options and scheduler of the disk/partition being used for testing. This information is subsequently displayed within the system information table. If the scheduler / mount options are maintained the same throughout all test runs, only a single line is displayed otherwise the options for each test run will be automatically displayed. The file-system in use is always captured and shown in the system information table.


      Phoromatic

      Overview

      Phoromatic is a remote management system for the Phoronix Test Suite. Phoromatic allows the automatic (hence the name Phoromatic) scheduling of tests, remote installation of new tests, and the management of multiple test systems all through an intuitive, easy-to-use web interface. Tests can be scheduled to automatically run on a routine basis across multiple test systems. The test results are then available from this central, secure location.

      Basic Instructions

      1. Create a free account at Phoromatic.com. Phoromatic can also be installed on a LAN / intranet for professional and enterprise support customers of the Phoronix Test Suite.
      2. On each test system, install the latest version of the Phoronix Test Suite and then run phoronix-test-suite module-setup phoromatic. During this process it will ask the user for an account code and activiation ID that are shown from the Systems page of your Phoromatic account.
      3. Phoromatic cannot install external dependencies for a test if the Phoronix Test Suite is not running as root, so it would be recommended to now run phoronix-test-suite install-dependencies all. Alternatively, you can also run phoronix-test-suite install all to install all tests at this time, or begin selectively installing the tests you wish to use. Phoromatic can install tests automatically though, it just cannot install external dependencies when the user is not root.
      4. When you are all set, run phoronix-test-suite phoromatic.start, which begins the process of the Phoronix Test Suite listening to the Phoromatic server waiting for installation and run commands, etc. The installed system software/hardware is also reported all automatically, etc.

      For more information on Phoromatic and a detailed guide, read Building A Benchmarking Test Farm With Phoromatic.


      PTS Desktop Live

      PTS Desktop Live 2010.1 "Anzhofen"

      PTS Desktop Live and PTS Netbook Live are Linux-based operating systems designed to provide a free software platform for carrying out system tests and hardware benchmarks in an automated, reproducible, and effective manner. The Phoronix Test Suite operating systems are designed around the Phoronix Test Suite with the operating system itself consisting of a stripped down Linux environment, then built upon that is the Phoronix Test Suite with its test profiles and suites. This is not a standard Linux desktop with the normal throng of packages.

      Testing with PTS Desktop Live is intended to be via a Live DVD or Live USB (i.e. flash drive or memory card) environment. PTS Netbook Live is similar to PTS Desktop Live but designed for testing on lightweight x86 systems and netbooks. Both PTS Desktop Live and PTS Netbook Live make it very easy to deploy the Phoronix Test Suite across an array of systems, isolates any software differences when seeking to perform hardware comparisons, and is designed to be very easy to carry out these Linux benchmarks even for a first-time Linux user.

      The inaugural release of this operating system was PTS Desktop Live 2009.3 (codenamed "Gernlinden") and was based upon the Phoronix Test Suite 2.0 release. The Gernlinden release shipped with more than 50 open-source test profiles and all needed files being located on the disc image. PTS Desktop Live uses the GTK2 GUI dialog for the Phoronix Test Suite by default, but the CLI options are also accessible. PTS Desktop Live also features optimizations to the Linux kernel and related components for use on the latest high-end hardware and other performance related tweaking. PTS Netbook Live features optimizations for the Intel Atom processor.

      The mission of the Phoronix Test Suite and related products will not be achieved until it has made Linux benchmarking incredibly robust and innovative, drop dead easy to perform nearly any kind of benchmark, and when it out-paces other leading operating systems for its benchmarking abilities. These operating systems are being updated quarterly in conjunction with new Phoronix Test Suite releases. The Phoronix Test Suite will continue to be supported under all other Linux distributions, OpenSolaris, Mac OS X, Windows, and *BSD operating systems, but this is just another addition on top of that.

      PTS Desktop Live is designed to run on x86_64 compatible systems with 2GB or more of system memory (ideally 4GB+ if you wish to run many of the tests in a live environment) being highly recommended along with a modern CPU and graphics processor. No proprietary graphics drivers are shipped with PTS Desktop Live at this time, so depending upon the hardware you may not have OpenGL acceleration to run the few graphics-related tests that are included with this release. Only graphics drivers are provided for ATI/AMD, NVIDIA, and Intel hardware. An Internet connection is not required but is needed for communication with OpenBenchmarking.org and for utilizing some of the other Phoronix Test Suite features.

      PTS Netbook Live is designed for netbooks and nettop computers with an Intel Atom processor.

      Quick Start Guide

      When the operating system has fully booted, the end-user agreement for the Phoronix Test Suite will be displayed, followed by initializing the main GTK user interface for the Phoronix Test Suite. The Phoronix Test Suite has more than 100 test profiles while there are about 50 test profiles featured within live environment, which are free software, do not pose significant install size problems, and are suitable for benchmarking from a live environment. By default, PTS Desktop Live and PTS Netbook Live will only show the test profiles and suites where all of the needed test files and dependencies ship with this open-source operating system. However, to access any of the test profiles that may require downloading additional files or external dependencies, use the View menu to toggle the different options. The system's hardware and software information can also be viewed in a graphical window from this menu.

      From the Available Tests tab, any test/suite can be selected to view more information. If you wish to install the test, simply click on the install button while waiting shortly for it to install. Afterwards, the test can be run by selecting it again and clicking on the run/benchmark button. If you have a OpenBenchmarking.org account, you can login from the File menu while Phoronix Test Suite settings are adjustable from the Edit menu.

      When the testing has completed, the graphical user interface will reappear. Via the buttons that appear at the top of the interface, the test results can then be opened within the web browser. Depending upon the test profile, it may also be possible to immediately compare the test result(s) against a set of reference systems. If the completed test(s) do have reference results available, a list of the comparable systems are shown, so that you can click on one or more of these reference systems to see how the given system performs in comparison. Results from OpenBenchmarking.org can also be compared with any of the test results.

      Assuming you did not launch any commands from the terminal to alter the disk(s) or its contents or carry out any other changes; PTS Desktop Live will have not touched your data or the installed operating system(s). If you wish to archive any of your test results, upload the results to OpenBenchmarking.org. Alternatively, when going to the Test Results tab and selecting a test, the File menu presents options for exporting results to text, CSV, and PDF files. The contents of the ~/.phoronix-test-suite/test-results/ folder can also be backed up for preserving the test results.

      If you wish to use the Phoronix Test Suite from the command-line, open a terminal and run phoronix-test-suite.


      Development Credits

      The Phoronix Test Suite is based upon the extensive testing and internal tools developed by Phoronix.com since 2004 along with support from leading tier-one computer hardware and software vendors. The principal architects of the Phoronix Test Suite are Michael Larabel and Matthew Tippett. The phoronix-test-suite, pts_Graph, bilde_renderer, Phodevi, tandem_Xml, and nye_Xml are some of the related open-source projects provided by Phoronix Media.

      Below is a list of individuals and organizations that have contributed upstream patches, test profiles, and/or made other contributions to the Phoronix Test Suite that Phoronix Media would like to thank.

      • Achim Gottinger
      • Achim Lange
      • Andrew Schofield
      • Apaige
      • Ben Kero
      • Bryan Quigley
      • Chris Campbell
      • Daniel Díaz
      • Daniel Stodden / Citrix
      • Dean Hilkewich
      • ESET s.r.o.
      • Fatima Sheremetyeva
      • Fujitsu
      • Hans Ulrich Niedermann
      • Intel Open-Source Technology Center
      • Jeroen van Rijn
      • Johannes Obermayr
      • Juan Aguado
      • Jörg Schirottke
      • Kenney Phillis
      • Kim Bisgaard
      • Laminar Research
      • Marco Poletti
      • Matthew Tippett
      • Michael Larabel
      • Michael Opdenacker
      • Michael Ploujnikov
      • Michal Zatloukal
      • Nils Kneuper
      • NVIDIA Corporation
      • Pekka Panula
      • Peter Kraus
      • Rainer König
      • SOMA Networks, Inc.
      • Stefan Doesinger
      • Stepan Hrbek
      • Stéphane Teletchéa
      • Sun Microsystems
      • Tao Zhang
      • Thomas Klausner
      • Unigine Corp
      • Vadim Peretokin
      • Zachary Powers

      Copyright © 2008 - 2013 by Phoronix Media.

      phoronix-test-suite/install-sh0000755000175000017500000001206112144771706016633 0ustar michaelmichael#!/bin/sh # Phoronix Test Suite # URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ # Copyright (C) 2008 - 2012, Phoronix Media # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Generic Phoronix Test Suite installer # To install into a chroot, set $DESTDIR to the corresponding directory. if [ "X$1" = "X" ] then INSTALL_PREFIX="/usr" else INSTALL_PREFIX="$1" fi # Ensure the user is in the correct directory if [ ! -f pts-core/phoronix-test-suite.php ] then cat <<'EOT' To install the Phoronix Test Suite you must first change directories to phoronix-test-suite/. For support visit: http://www.phoronix-test-suite.com/ EOT exit fi mkdir -p $DESTDIR$INSTALL_PREFIX if [ ! -w $DESTDIR$INSTALL_PREFIX ] then echo "\nERROR: $DESTDIR$INSTALL_PREFIX is not writable. Run this installer as root or specify a different directory prefix as the first argument sent to this script.\n" exit fi rm -rf $DESTDIR$INSTALL_PREFIX/share/phoronix-test-suite/ rm -rf $DESTDIR$INSTALL_PREFIX/share/doc/phoronix-test-suite/ mkdir -p $DESTDIR$INSTALL_PREFIX/bin/ mkdir -p $DESTDIR$INSTALL_PREFIX/share/applications/ mkdir -p $DESTDIR$INSTALL_PREFIX/share/icons/hicolor/48x48/apps/ mkdir -p $DESTDIR$INSTALL_PREFIX/share/man/man1/ mkdir -p $DESTDIR$INSTALL_PREFIX/share/phoronix-test-suite/ mkdir -p $DESTDIR$INSTALL_PREFIX/share/doc/phoronix-test-suite/ mkdir -p $DESTDIR$INSTALL_PREFIX/../etc/bash_completion.d/ cp CHANGE-LOG $DESTDIR$INSTALL_PREFIX/share/doc/phoronix-test-suite/ cp COPYING $DESTDIR$INSTALL_PREFIX/share/doc/phoronix-test-suite/ cp AUTHORS $DESTDIR$INSTALL_PREFIX/share/doc/phoronix-test-suite/ cd documentation/ cp -r * $DESTDIR$INSTALL_PREFIX/share/doc/phoronix-test-suite/ cd .. rm -rf $DESTDIR$INSTALL_PREFIX/share/doc/phoronix-test-suite/man-pages/ cp documentation/man-pages/*.1 $DESTDIR$INSTALL_PREFIX/share/man/man1/ cp pts-core/static/bash_completion $DESTDIR$INSTALL_PREFIX/../etc/bash_completion.d/phoronix-test-suite cp pts-core/static/images/phoronix-test-suite.png $DESTDIR$INSTALL_PREFIX/share/icons/hicolor/48x48/apps/phoronix-test-suite.png cp pts-core/static/phoronix-test-suite.desktop $DESTDIR$INSTALL_PREFIX/share/applications/ cp pts-core/static/phoronix-test-suite-launcher.desktop $DESTDIR$INSTALL_PREFIX/share/applications/ rm -f $DESTDIR$INSTALL_PREFIX/share/phoronix-test-suite/pts/etc/scripts/package-build-* cp -r pts-core $DESTDIR$INSTALL_PREFIX/share/phoronix-test-suite/ rm -f $DESTDIR$INSTALL_PREFIX/share/phoronix-test-suite/pts-core/static/phoronix-test-suite.desktop rm -f $DESTDIR$INSTALL_PREFIX/share/phoronix-test-suite/pts-core/static/phoronix-test-suite-launcher.desktop rm -f $DESTDIR$INSTALL_PREFIX/share/phoronix-test-suite/pts-core/openbenchmarking.org/openbenchmarking-mime.xml rm -f $DESTDIR$INSTALL_PREFIX/share/phoronix-test-suite/pts-core/static/bash_completion rm -f $DESTDIR$INSTALL_PREFIX/share/phoronix-test-suite/pts-core/static/images/openbenchmarking.png rm -f $DESTDIR$INSTALL_PREFIX/share/phoronix-test-suite/pts-core/static/images/%phoronix-test-suite.png sed 's:PTS_DIR=`pwd`:PTS_DIR='"$INSTALL_PREFIX"'\/share\/phoronix-test-suite:g' phoronix-test-suite > $DESTDIR$INSTALL_PREFIX/bin/phoronix-test-suite chmod +x $DESTDIR$INSTALL_PREFIX/bin/phoronix-test-suite # sed 's:\$url = PTS_PATH . \"documentation\/index.html\";:\$url = \"'"$INSTALL_PREFIX"'\/share\/doc\/packages\/phoronix-test-suite\/index.html\";:g' pts-core/commands/gui_gtk.php > $DESTDIR$INSTALL_PREFIX/share/phoronix-test-suite/pts-core/commands/gui_gtk.php # XDG MIME OpenBenchmarking support if [ "X$DESTDIR" = "X" ] then #No chroot xdg-mime install pts-core/openbenchmarking.org/openbenchmarking-mime.xml xdg-icon-resource install --context mimetypes --size 64 pts-core/static/images/openbenchmarking.png application-x-openbenchmarking else #chroot mkdir -p $DESTDIR$INSTALL_PREFIX/share/mime/packages/ mkdir -p $DESTDIR$INSTALL_PREFIX/share/icons/hicolor/64x64/mimetypes/ cp pts-core/openbenchmarking.org/openbenchmarking-mime.xml $DESTDIR$INSTALL_PREFIX/share/mime/packages/ cp pts-core/static/images/openbenchmarking.png $DESTDIR$INSTALL_PREFIX/share/icons/hicolor/64x64/mimetypes/application-x-openbenchmarking.png fi echo -e "\nPhoronix Test Suite Installation Completed\n Executable File: $INSTALL_PREFIX/bin/phoronix-test-suite Documentation: $INSTALL_PREFIX/share/doc/phoronix-test-suite/ Phoronix Test Suite Files: $INSTALL_PREFIX/share/phoronix-test-suite/\n" if [ "X$DESTDIR" != "X" ] then echo "Installed to chroot: $DESTDIR" echo "Please update your desktop and mime-database manually" fi phoronix-test-suite/phoronix-test-suite.bat0000755000175000017500000000265412077607365021307 0ustar michaelmichael:: Phoronix Test Suite :: URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ :: Copyright (C) 2008 - 2013, Phoronix Media :: Copyright (C) 2008 - 2013, Michael Larabel :: phoronix-test-suite: The Phoronix Test Suite is an extensible open-source testing / benchmarking platform :: :: This program is free software; you can redistribute it and/or modify :: it under the terms of the GNU General Public License as published by :: the Free Software Foundation; either version 3 of the License, or :: (at your option) any later version. :: :: This program is distributed in the hope that it will be useful, :: but WITHOUT ANY WARRANTY; without even the implied warranty of :: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the :: GNU General Public License for more details. :: :: You should have received a copy of the GNU General Public License :: along with this program. If not, see . :: :: Full path to root directory of the actual Phoronix Test Suite code @echo off set PTS_DIR=%pwd% set PTS_MODE=CLIENT :: TODO: Other work to bring this up to sync with the *NIX phoronix-test-suite launcher If exist "C:\Program Files (x86)\PHP"\php set PHP_BIN="C:\Program Files (x86)\PHP"\php If exist C:\php-gtk2\php set PHP_BIN=C:\php-gtk2\php set PHP_BIN="C:\Program Files (x86)\PHP"\php If not defined PHP_BIN echo "\nPHP could not be found.\n" else cls %PHP_BIN% pts-core/phoronix-test-suite.php %* phoronix-test-suite/phoronix-test-suite0000755000175000017500000000575712201220062020517 0ustar michaelmichael#!/bin/sh # # Phoronix Test Suite # URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ # Copyright (C) 2008 - 2013, Phoronix Media # Copyright (C) 2008 - 2013, Michael Larabel # phoronix-test-suite: The Phoronix Test Suite is an extensible open-source testing / benchmarking platform # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Full path to root directory of the actual Phoronix Test Suite code # export PTS_DIR=$(readlink -f `dirname $0`) export PTS_DIR=`pwd` export PTS_MODE="CLIENT" if [ $PTS_DIR != `pwd` ] then cd $PTS_DIR fi # Determine PHP binary location if [ ! "X$PHP_BIN" = "X" ] && [ -x $PHP_BIN ] then export PHP_BIN=$PHP_BIN elif [ -x /usr/bin/php5 ] || [ -x /usr/local/bin/php5 ] || [ -x /usr/pkg/bin/php5 ] then export PHP_BIN="php5" elif [ -x /usr/bin/php ] || [ -x /usr/local/bin/php ] || [ -x /usr/pkg/bin/php ] then export PHP_BIN="php" elif [ -x /usr/php5/bin/php ] then export PHP_BIN="/usr/php5/bin/php" elif [ -x /usr/php/bin/php ] then export PHP_BIN="/usr/php/bin/php" elif [ -x /opt/bin/php ] then export PHP_BIN="/opt/bin/php" elif [ -x /usr/pkg/libexec/cgi-bin/php ] then export PHP_BIN="/usr/pkg/libexec/cgi-bin/php" elif [ -x /usr/bin/hhvm ] then export PHP_BIN="/usr/bin/hhvm" else export PHP_BIN="" fi # Make sure PHP is installed if [ "X$PHP_BIN" = "X" ] then cat <<'EOT' PHP 5.2 or newer must be installed for the Phoronix Test Suite The PHP command-line package is commonly called php-cli, php5-cli, or php. For more information visit: http://www.phoronix-test-suite.com/ EOT if [ -x /usr/bin/apt-get ] then echo "The command to likely run for your operating system is: " echo "# apt-get install php5-cli php5-json php5-gd" echo " " elif [ -x /usr/bin/yum ] then echo "The command to likely run for your operating system is: " echo "# yum install php-cli php-xml" echo " " fi exit fi # Ensure the user is in the correct directory if [ ! -f pts-core/phoronix-test-suite.php ] then cat <<'EOT' To run the Phoronix Test Suite locally you must first change directories to phoronix-test-suite/ or install the program using the install-sh script. For support visit: http://www.phoronix-test-suite.com/ EOT exit fi # Command-specific conditions case "$1" in "test-module" | "debug-module") export PTS_IGNORE_MODULES=1 ;; esac # Run The Phoronix Test Suite PTS_EXIT_STATUS=8 while [ $PTS_EXIT_STATUS -eq 8 ]; do $PHP_BIN pts-core/phoronix-test-suite.php $@ PTS_EXIT_STATUS=$? done phoronix-test-suite/CHANGE-LOG0000644000175000017500000037363512223157044016126 0ustar michaelmichaelPHORONIX TEST SUITE CHANGE-LOG Phoronix Test Suite 4.8.3-Sokndal 2 October 2013 - pts-core: Fix openmpi on Gentoo external dependency - pts-core: Detect graphics comparison when GPU changes with audio string - pts-core: Don't use HTTPS on proxies when connecting to OpenBenchmarking.org - pts-core: Add VersionSpecific capability to external dependencies handling for package(s) that may only be in certain OS versions - pts-core: Ensure xscreensaver is deactivated - pts-core: Support toggling GNOME3 screensaver on GNOME 3.8+ where org.gnome.desktop.screensaver idle-activation-enabled -> org.gnome.desktop.session idle-delay - phodevi: Fix for parsing long PCI string values - phodevi: Improve Intel GPU model detection with recent xf86-video-intel DDX Phoronix Test Suite 4.8.2-Sokndal 30 August 2013 - pts-core: Fix for reporting environment variables to system notes on system graph table - pts-core: Fix OpenBenchmarking.org class issue for select code paths Phoronix Test Suite 4.8.1-Sokndal 14 August 2013 - pts-core: Fix OpenBenchmarking.org log-ins Phoronix Test Suite 4.8.0-Sokndal 13 August 2013 - pts-core: When PHP is missing, for apt-get/yum distributions report the likely command needed to run - pts-core: Don't prompt to install missing/failed tests when using the 'benchmark' command - phodevi: Support for reading the Radeon DRM driver's current core/memory frequencies when DPM is enabled (Linux 3.11+) - phodevi: Support for reading the top Radeon DRM driver core/memory frequency via dmesg when DPM is enabled (Linux 3.11+) - phodevi: Support for reading the Radeon DRM driver's current GPU (vddc) voltage when DPM is enabled (Linux 3.11+) - phoromatic: Updated module against latest upstream Phoromatic.com Server Phoronix Test Suite 4.8 Milestone 5 6 August 2013 - pts-core: Add php5-json as a dependency now on Debian packages since Ubuntu split it up and no longer in php5-cli - pts-core: Add support for reporting set kernel module parameters to notes on the system table graph - pts-core: Add support for reporting of important environment variables to notes on the system table graph - pts-core: Changes needed for modern Phoromatic - pts_Graph: Add new automated color chooser for line graph color selection - pts_Graph: Slight rework to code handling the remove of common words from result identifiers - phodevi: Add support for Intel DRM driver's gt_max_freq_mhz for obtaining maximum GPU frequency on modern kernels - phodevi: Add support for Intel DRM driver's gt_cur_freq_mhz for obtaining current GPU frequency on modern kernels - phodevi: Only prepend AIB vendor to NVIDIA and AMD GPU strings - phodevi: Add system.kernel-parameters property for reading kernel command line parameters - phodevi: Add support for checking the __GL_FSAA_MODE environment variable - phodevi: Add support for checking the __GL_LOG_MAX_ANISO environment variable - phodevi: Add 0xc36400 super block for CephFS - phodevi: Add unity-system-compositor version detection Phoronix Test Suite 4.8 Milestone 4 24 July 2013 - pts-core: Add initial support for test profile's downloads.xml to have a SHA256 hash for files - pts-core: Rename NO_MD5_CHECKS environment variable to NO_FILE_HASH_CHECKS - pts-core: Add PTS5 codenames from Tulskaya oblast / Tula Oblast Russian region - pts-core: Support fixes for Facebook HipHop Virtual Machine for PHP HHVM 2.1.0 - pts-core: Fix text corruption bug with auto shortening of identifiers on multi-way comparisons - pts_Graph: Fix auto shortening when the first identifier is only one word - phodevi: Support ECS and eVGA graphics card AIB vendor detection Phoronix Test Suite 4.8 Milestone 3 19 July 2013 - pts-core: Add few more cases of error detection on failed test install - pts-core: Round download size totals in the concise display mode for large files - pts-core: Add missing PreInstallMessage and PostInstallMessage to the OpenBenchmarking.org test profile schema and writer - pts-core: Allow test results to have "secondary_linked_results" - pts-core: Add initial support for frame latency / jitter secondary result graphs - pts_Graph: Assume any version of Google Chrome/Chromium can render SVG - pts_Graph: Only prepend 'v' to version string on graphs if first character is numeric - toggle-screensaver: Support doing "xscreensaver-command -exit" when needed - phodevi: Add more stock fallback display modes - phodevi: Ensure MB/GB are reported on OS X memory strings - phodevi: Workaround Linux 3.10 kernel reporting bogus frequencies for scaling_max_freq on some Intel CPUs - phodevi: Support prepending the graphics card / AIB vendor on GPU strings Phoronix Test Suite 4.8 Milestone 2 6 July 2013 - pts-core: Expand Mandriva Linux external dependency support to distributions having urpmi - pts-core: Add Apple OS X font paths for use by the GD graph renderer - pts-core: Add "/usr/lib64/" to the automated external dependency verification path - pts-core: Allow passing multiple test identifiers to remove with remove-from-result-file command - pts-core: Give a warning when the results viewer opens in the KDE Konqueror web-browser - phodevi: Break operating system string at "(" - phodevi: Don't return "n/a" from LSB release strings - phodevi: IceWM window manager detection - phodevi: Add gpu.temp safety check to prevent against AMD Catalyst OverDrive sending garbage - phodevi: Fix for XRandR resolution query on XMir - phodevi: Support using systemd-detect-virt as fallback for detecting Linux virtualization method Phoronix Test Suite 4.8 Milestone 1 20 June 2013 - pts-core: Don't show null error strings on failed test installations - pts-core: Allow test profiles to pass min/max data results through JSON to graphs using MIN_ and MAX_ prefixes - pts-core: Support displaying min/max data from the concise (default) display mode text output - phodevi: MHz -> GHz fix for the cpu.freq sensor on Apple OS X - phodevi: Add fallback support for using ioreg for calculating sys.power power draw on Apple OS X - phodevi: Support reporting multiple monitor models from Xorg.0.log Phoronix Test Suite 4.6.1-Utsira 6 June 2013 - pts-core: Add ONLY_TEST_TYPES environment variable for skipping test profiles that don't belong to a certain hardware type - pts-core: Ensure extract-from-result-file opens the proper HTML web-browser - pts-core: Ensure copy-run-in-result-file opens the proper HTML web-browser - pts-core: Ensure reorder-result-file opens the proper HTML web-browser - pts-core: Ensure rename-identifier-in-result-file opens the proper HTML web-browser - pts-core: Ensure remove-from-result-file opens the proper HTML web-browser - pts-core: Reworked handling of browser launching in batch mode - pts-core: Launch the web browser to display results when using internal-run mode - phodevi: Add Haswell BMI2 detection - phodevi: Support vm_stat with the memory.usage sensor, works on OS X - phodevi: Add new network.usage sensor for Apple OS X contributed by ESET Phoronix Test Suite 4.6.0-Utsira 21 May 2013 - phodevi: Report CPU scaling driver along side the CPU scaling governor Phoronix Test Suite 4.6 Milestone 2 16 May 2013 - pts-core: Support compiler masking on short binaries - pts-core: More advanced detection of compiler flags within the compiler masking process - pts-core: DragonFlyBSD external dependency packaging updates - pts-core: Various fixes - phodevi: Fix for cpu.freq sensor reading on Apple OS X Phoronix Test Suite 4.6 Milestone 1 11 April 2013 - pts-core: Official support for Facebook's HipHop HHVM PHP - pts-core: Introduce new pts_define interface - pts-core: Add debug-self-test option for running a self-hosting PHP/PTS performance test - pts-core: Support PHP 5.4's cli_set_process_title() function - pts-core: For now don't use PHP CURL on HipHop HHVM due to issues - pts-core: Ubuntu 13.04's sudo seems to have problems with the external dependency handling - pts-core: Add internal-run command for running benchmarks in semi-automated manner and without uploading data to OpenBenchmarking.org - phodevi: Fix for memory reporting on OS X - phodevi: Improved LLVM Clang compiler version detection with modern Apple Xcode - phodevi: Improved Intel Linux GPU overclocking frequency detection - phodevi: Fix for detecting new (319.xx) NVIDIA Linux driver X.Org driver Phoronix Test Suite 4.4.1-Forsand 14 March 2013 - pts-core: Add the arm-linux-gnueabihf library directory for PTS External Dependency checks - pts-core: Add SKIP_ALL_TEST_SUPPORT_CHECKS environment variable - pts-core: Fix screen resolution listening when the resolution fails to be detected through Phodevi - pts-core: Update openSUSE external dependencies - pts-core: Strip "project" from reported strings - phodevi: Add support for detecting the Razor-qt desktop environment - phodevi: No longer report the Catalyst marketing version number since the DDX is no longer reporting it reliably - phodevi: Detect if the X.Org Server DDX module was unloaded - phodevi: Reorder DDX driver fallback detection - phodevi: Cleanse eCryptfs sig and cipher from showing in mounts file - phodevi: Improve Linux memory RAM type detection Phoronix Test Suite 4.4.0-Forsand 26 February 2013 - pts-core: Improvement for detecting installed libraries for external dependency handling - pts-core: Address redundant dash handling within the result file save name - phodevi: Support for detecting SurfaceFlinger (Google Android) - phodevi: Ensure non-ASCII characters are removed from Phodevi properties - phodevi: Support for reading the OpenGL Core Profile information via glxinfo Phoronix Test Suite 4.4 Milestone 3 14 February 2013 - pts-core: Incorporate xx.yy (of xx.yy.zz) test profile version string into test result comparison_hash - pts-core: Return contained tests hash for result files as a raw SHA1 - pts-core: Improving passing of compiler flags/options to be reported on test result graphs - pts-core: Support specifying just relative include files, shared libraries, and command names for file check in PTS External Dependencies - pts-core: Faster PTS External Dependencies resolution and file checking - pts-core: Support for falling back right away to the generic file check lists for packages if not supplied by OS-specific list - pts-core: Add MacPorts PTS External Dependencies support for handling some package dependencies on Apple Mac OS X - pts-core: Allow 3D tests to run when LLVMpipe OpenGL is present regardless of the display driver loaded for the graphics card - phodevi: Add file-system magic blocks for eCryptfs, AuFS, LustreFS, and Panasas PanFS - phodevi: Add AVX2 (Advanced Vector Extensions 2) CPU instruction set detection - phodevi: Support for detecting the new F2FS file-system Phoronix Test Suite 4.4 Milestone 2 30 January 2013 - pts-core: Improvement for detecting errors from failed test installations - pts-core: Allow "Deprecated" flag for ProfileStatus in the XML test profile schema - pts-core: Support for scanning test run log files automatically to look for errors when tests fail to execute - pts-core: Remove duplicate "libtool" PTS External Dependency - pts-core: Complete rewrite of the FreeBSD external dependency handling to use ports collection - pts-core: Enable BSD support for checking exit codes on test installation and test execution - pts-core: Various BSD support improvements - pts-core: Begin on DragonFlyBSD pkgsrc-based external dependency solution - phodevi: Fix to improve Xfce version detection when Gtk-Warnings are thrown before the version string - phodevi: Add Enlightenment desktop environment detection support - phodevi: Add Consort Desktop Environment (GNOME Fork) detection support Phoronix Test Suite 4.4 Milestone 1 23 January 2013 - pts-core: Introduce 'common-dependencies' concept to PTS External Dependencies - pts-core: Fix reporting of some already installed dependencies - pts-core: Support for listing 'local/' tests from the list-supported-tests command - pts-core: Support for test profiles providing a 'support-check.sh' file - pts-core: Support for reporting the Graphics AA/AF values to the system notes table - pts-core: Add a public version of the TODO list - pts-core: Don't attempt copying install.log to install-failed.log on empty files - pts-core: Add fallback to allow matching an operating system to an external dependencies package list based upon the detected package manager - pts-core: When anonymous usage reporting is enabled, report test installation failures to OpenBenchmarking.org for analyzing problem - pts-core: Support for detecting common errors within test profile install failures and reporting the relevant information to the user - pts-core: When installing many tests and there are install failures, conveniently show the errors at the end - pts-core: When installing multiple tests, report any unknown test profiles/suites - pts-core: Faster loading of list-available-tests command by not forcing all test profile data be downloaded - pts-core: Progressively download OpenBenchmarking.org in list-available-suites command to display information faster - phodevi: Improve Nouveau video RAM memory capacity detection on newer Linux kernels - phodevi: Warning fix for Radeon GPU frequency detection - phodevi: Drop "special_settings_string" support - phodevi: Support for checking if the Gallium3D anti-aliasing level was overrode using GALLIUM_MSAA environment variable Phoronix Test Suite 4.2.0-Randaberg 20 December 2012 - pts-core: Fix SVG render detection on Firefox/Gecko 17.0 - pts-core: Fix for breaking quoted args with internal spaces (reported by _rubio_) - pts-core: Add glibc-static to build-utilities external dependency on Fedora - pts-core: Fix for using the SKIP_TESTS environment variable causing a fatal error - pts-core: Phoronix Test Suite 4.4 is codenamed Forsand - phodevi: Improved detection of power consumption from batteries in certain Linux configurations Phoronix Test Suite 4.2 Milestone 3 22 November 2012 - pts-core: Don't report null times for estimated run-time - phodevi: Support for determining the build configuration on LLVM 3.2 where llvm-ld is llvm-link - phodevi: Hard fall-back support for detecting the xf86-video-modesetting driver usage - toggle_screensaver: Disable blanking of the terminal screen when running tests Phoronix Test Suite 4.2 Milestone 2 22 October 2012 - pts-core: Add list-recommended-tests option for providing subsystem test recommendations based upon OpenBenchmarking.org popularity/usage - pts-core: Add auto-compare option for automatically determining relevant OpenBenchmarking.org result comparisons based upon software/hardware - pts-core: Allow passing test profile names to auto-compare to seed it with the test(s) you wish to use for comparison - pts-core: OpenBenchmarking.org now supports system log payload sizes up to 2MB - pts-core: Object-ify PTS external dependency handling - phodevi: Split some functions into new phodevi_base class Phoronix Test Suite 4.2 Milestone 1 8 October 2012 - pts-core: Support download caches at /media/*/*/download-cache/ - pts-core: Support OPENGL_DRIVER as a run-time variable - pts-core: For external dependency handling, treat Linaro as Ubuntu - pts-core: Check for null distribution-specific external dependency package names - pts-core: Formatting improvements to result-file-to-text output - pts-core: Add openssl-development as a new test external dependency - pts-core: Don't warn on out-of-date test profiles when being run in batch mode - phodevi: Support for reading the VirtualBox version of Beta/RC versions - phodevi: Better support detection for Exynos ARM cores - phodevi: Initial support for reading node power over IPMI - phodevi: Initial support for reading core temperature over IPMI - phodevi: On Linux attempt to determine the install RAM's vendor and product part number - toggle_screensaver: Support for module suspending the Xfce4 desktop screensaver using xfconf-query - pts_Graph: Fix for vertical/rotated text in SVG -> GD translation Phoronix Test Suite 4.0.1 21 August 2012 - pts-core: Allow shortened test profile versions inputted by user to be expanded to matching latest version in stream - pts-core: Allow shortened test suite versions inputted by user to be expanded to matching latest version in stream - pts-core: Add list-unsupported-tests option for debugging purposes - pts-core: Add subversion as a PTS External Dependency - pts-core: Add git as a PTS External Dependency - pts-core: Add superlu as a PTS External Dependency - pts-core: Add libtool as a PTS External Dependency - pts-core: Hash within the result file all of the contained tests - pts-core: Support for anonymous usage reporting of test installation times to OpenBenchmarking.org - phodevi: Fix memory RAM DIMM count detection in select configurations - phodevi: Intel GPU string reporting improvement - phodevi: Support for detecting multiple GPUs on Apple OS X - phodevi: Support for detecting Gallium3D XA - phodevi: Support for llvm-link on LLVM 3.2svn Phoronix Test Suite 4.0.0-Suldal 23 July 2012 - pts-core: Initial implementation of the PTS4 Local Results Viewer - pts-core: Initial command of ob-test-profile-analyze - pts-core: Fix for installing Ubuntu external dependencies in a headless mode - pts-core: Disable webui since it won't be ready until PTS 4.2 - pts-core: External dependencies fix for SUSE Linux Enterprise Server 11 - phodevi: Additional fall-back support when GPU driver doesn't expose all standard mode-setting modes - phodevi: Support for detecting and reading the version of the Cinnamon Desktop Environment - timed_screenshot: Overhaul of the timed screenshot PTS module - timed_screenshot: Compress PNG images Phoronix Test Suite 4.0 Milestone 4 29 June 2012 - pts-core: Support download caches at /run/media/*/*/download-cache/ - pts-core: Set SKIP_TEST_SUPPORT_CHECKS=1 environment variable for debugging purposes to run tests on unsupported platforms - pts_Graph: Only render as much room for pts_OverViewGraph as there are for what will be rendered (bar graph values) - phodevi: Ensure DVD drives don't get reported on BSD operating systems when requesting disk drives - phodevi: Improve graphics processor detection on Solaris 11 11/11 for non-NVIDIA GPUs - system_monitor: Add support for handling i915_energy monitor reading in microJoules for each test run - system_monitor: Place timer support for individual test runs within the module Phoronix Test Suite 4.0 Milestone 3 22 May 2012 - pts-core: Reformat user configuration input on test run - pts-core: Improve no-network support handling - pts-core: Streamline detailed-system-info collection - pts-core: Invalid command improvements - pts-core: Various alterations - pts-core: Make greater use of trigger_error - pts-core: Generate more relevant default result identifier strings based on subsystems under test on empty input - phodevi: Support to attempt to detect the file-system underneath ecryptfs - pts-core: Debian control script update Phoronix Test Suite 4.0 Milestone 2 29 April 2012 - pts-core: Better recognize some open-source vs. closed-source graphics card/driver combination comparisons - pts-core: Fix potential crash in list-test-usage command - pts-core: Support for detecting FSGSBASE and RDRAND on Intel Ivy Bridge - pts-core: When detecting a CPU comparison, report the detailed CPU system table information - pts-core: When detecting a GPU/OpenGL comparison, report the detailed GPU system table information - pts-core: Fix PRESET_OPTIONS failing when specifying an option value rather than its index - pts-core: Archive vdpauinfo when available - phodevi: Detection support for Intel IOC (Intel Offline Compiler) OpenCL SDK - phodevi: Support for detecting GLAMOR (Intel OpenGL-accelerated X.Org Driver) acceleration - pts_Graph: Fix rounding issue on pts tables that are very wide - pts_Graph: Add SideViewTable - documentation: Add a basic text README to the root phoronix-test-suite directory Phoronix Test Suite 4.0 Milestone 1 12 April 2012 - pts-core: Add AutoSortRunQueue option that by default automatically sorts the test execution queue to run similar tests together - pts-core: Expose more verbose information within detailed-system-info command - pts-core: Remove recover-run command since with new PTS4 changes the finish-run command will provide the same functionality - pts-core: Track the CPU scaling governor configuration between test runs - pts-core: Report 2D acceleration information to system table report on graphics test runs - pts-core: Support for showing test notes on multi-way comparisons - pts-core: Fix compatibility with the new pts_Graph renderer back-end for result-file-to-pdf option - pts-core: Add p7zip as a possible external dependency - pts-core: When running OpenCL tests, report the number of available compute cores - pts_Graph: Begin work on PHP 5.4 "webui" option (currently far from incomplete/experimental) - pts_Graph: Tweak spacing on pts_Table - pts_Graph: Re-factor most text vertical offsets to not use dominant-baseline since Opera still doesn't support this SVG attribute properly - pts_Graph: Begin unifying the Phoronix Test Suite and OpenBenchmarking.org theme - pts_Graph: Fix for emitted GD poly-lines being always black - pts_Graph: Begin work on block diagram graph (currently incomplete/experimental) - phodevi: Remove support for the deprecated HAL Linux fall-backs - phodevi: LLVM compiler reporting build configuration enhancements - phodevi: Support for reporting multiple mmcblk* disk devices - phodevi: Report /sys/hypervisor/type as a system layer - phodevi: Fix LXDE version detection - phodevi: Support for reporting the Openbox version - phodevi: Read Nouveau clock current frequencies rather than maximum frequencies (performance_level) - phodevi: Initial implementation of the Phodevi VFS (Virtual File-System; Still A Work In Progress) - graphics_event_checker: Override NVIDIA SyncToVBlank so it's always disabled - system_monitor: Allow performance per Watt to be automatically calculated if PERFORMANCE_PER_WATT is set Phoronix Test Suite 3.8.0-Bygland 19 March 2012 - pts-core: Support longer titles on result files (64 characters expanded on OpenBenchmarking.org) - pts-core: Wine/Windows fixes for items reported by Stefan Dösinger - pts-core: Minor improvement for analyzing compiler option string differences - pts-core: Fix for result file analyzing sometimes not returning hardware changes - pts-core: Better handling for detecting Wine trackers / other trackers using a mix of short SHA1s - phodevi: Support for determining and appending release dates on GCC snapshots/pre-releases Phoronix Test Suite 3.8 Milestone 3 13 March 2012 - pts-core: Introduce a look-aside download cache that automatically checks other existing test installations for needed files - pts-core: Support a last-minute look-aside copy if a previous test in the install queue downloaded the same file - pts-core: Attempt to detect when any test ends prematurely with an invalid result - pts-core: Begin reporting test installation compiler attributes from test profiles to the JSON in new result file XML schema - pts-core: Remove timestamps from captured log files - pts-core: Support system JSON for each identifier in the result file XML schema - pts-core: Fix save name issue when dealing with dashes mixed with spaces in save name - pts-core: Pass compiler options to graphs for reporting - pts-core: Report compiler configuration (GCC's "Configured with") to test system table when it changes between runs in a result file - pts-core: Report disk scheduler / mount options to test system table when disk tests are contained in result file - pts_Graph: Add support for reporting test notes to graphs - pts_Graph: Restore links within tables for the new pts_Graph table SVG DOM IR - pts_Graph: Fix for key not appearing on overview graph - pts_Graph: Embed PTS and OpenBenchmarking.org logos locally within SVG - pts_Graph: Support for representing web links on images within the new SVG DOM IR - pts_Graph: Support for word-wrapping test notes with long lines - phodevi: Fix for Linux memory module count decoding in niche cases on multi-socket systems - phodevi: Support for detecting all file-system mount options on test install path - phodevi: Initial work towards Minix 3.2.0 operating system support - graphics_event_checker: Rewrite of the graphics event checker and enable by default on new installs Phoronix Test Suite 3.8 Milestone 2 20 February 2012 - pts-core: Allow up to 1MB of system log files to be attached and uploaded to OpenBenchmarking.org - pts-core: Fix test profile / test suite identifier base name parsing on version handling - pts-core: Add cairo-development as an external dependency for Cairo drawing library development - pts-core: Initial support for compiler masking / compiler option intercepting on test installation - pts-core: Support symlinked ~/.drirc to test install directories - pts-core: Support for Mac OS X 10.8 "Mountain Lion" Developer Preview 1 - phodevi: Better recognition of Samsung disk drives - phodevi: NVIDIA CUDA (nvcc) detection and report it to system information compiler area - phodevi: Detection support for Microsoft Hyper-V virtualization server - phodevi: Detection support for Parallels Virtualization - phodevi: Better VMware DDX driver detection when using vmwgfx - phodevi: Support for detecting VirtualBox version using vboxguest kernel module information - phodevi: Support for detecting Portland Group (PGI) Workstation compilers - phodevi: Improved detection of Hitachi disk drives - phodevi: Support for Mac OS X 10.8 "Mountain Lion" Developer Preview 1 - pts_Graph: Rendering corrections of SVG DOM IR Phoronix Test Suite 3.8 Milestone 1 17 January 2012 - pts-core: When time-zone is not set in PHP, attempt to query it from the host system - pts-core: Fix for handling user variable swaps on the result identifier - pts-core: Major enhancements to MATISK testing module - pts-core: Fix for some hardware/software comparisons being turned into line graphs - pts-core: Dump some common / important environmental variables to system log area - pts-core: Migrate to a JSON-based graph configuration file at ~/.phoronix-test-suite/graph-config.json - pts_Graph: New version of pts_Graph that uses SVG DOM IR directly - pts-core: Allow pts_svg_dom to be converted to JPEG/PNG using new library as bilde_renderer replacement - phodevi: Add some fall-back graphics detection support of Texas Instruments OMAP / Samsung EXYNOS - phodevi: Fall-back graphics detection support for the ARM Mali - phodevi: NVIDIA TEGRA hardware detection improvements (as tested on a TEGRA-2 CompuLab TrimSlice) - phodevi: Further fall-back support for further detecting EXT3/EXT4 file-system from user-space - phodevi: Improve Arch Linux OS detection on at least ARM platforms - phodevi: Screen resolution fall-back of reading frame-buffer virtual size - phodevi: Improved Intel chipset detection parsing from Xorg.0.log when /sys/kernel/debug/ isn't readable - installer: Installer update Phoronix Test Suite 3.6.1-Arendal 23 December 2011 - pts-core: Various minor fixes - pts-core: Support launching the PTS Results Viewer in IceWeasel - phodevi: Support new Intel GPU name deciphering - phodevi: BSD support for reading motherboard information from kenv - phodevi: Support for fbdev X.Org DDX driver detection on fall-back after vesa driver - phodevi: OLPC Sugar Desktop Environment detection - phodevi: OLPC Fedora external dependencies support Phoronix Test Suite 3.6.0-Arendal 13 December 2011 - pts-core: Add "Possible Suggestions" to the invalid command output on install/run/benchmark commands based upon soundex - pts-core: Add SKIP_EXTERNAL_DEPENDENCIES support as more versatile option to NO_EXTERNAL_DEPENDENCIES - pts-core: Support for detecting PHP at /usr/pkg/libexec/cgi-bin/php - pts-core: Support for ClearOS Core Server - pts-core: Minor enhancements to DragonflyBSD 2.10 support - pts-core: Fix for error crash on virtual suite execution when selecting all tests to run - phodevi: CPU, disk, network detection improvements for FreeBSD/PC-BSD - phodevi: Minor support enhancements to OpenBSD 5.0 amd64 Phoronix Test Suite 3.6 Milestone 4 8 December 2011 - pts-core: Clean-up some of the test run output in the concise display mode - pts-core: When uploading a test profile to OpenBenchmarking.org, refresh the repository indexes afterwards - pts-core: When uploading a test suite to OpenBenchmarking.org, refresh the repository indexes afterwards - pts-core: Issue a notice when running an out-of-date version of a test profile - pts-core: When cloning results from OpenBenchmarking.org, also fetch the system logs from OpenBenchmarking.org - pts-core: Add openbenchmarking-changes command for seeing recently changed test profiles from OpenBenchmarking.org - phodevi: Fix for latest Catalyst Linux driver reporting odd OpenGL version (GL_VERSION) string - phodevi: Improve Debian non-Linux OS (kFreeBSD/Hurd) detection - phodevi: Allow lspci information to be used on Debian GNU/kFreeBSD - phodevi: Fallback for trying to read the Radeon DRM video memory from dmesg - phodevi: Further fallbacks for DRM video RAM size detection - phodevi: Add initial GPU voltage sensor - phodevi: Ensure no available modes are repeated - pts_Graph: If all result lines are flat (i.e. no change), just convert it to a bar graph Phoronix Test Suite 3.6 Milestone 3 1 December 2011 - pts-core: On large result files, auto-remove redundant words present in all identifiers - pts-core: When a command fails, allow helpful user information to be provided on a per-command basis - pts-core: More efficient trimming of redundant spaces - pts-core: Fix for identifiers being passed to graphs being corrupted when passing them multiple times - phodevi: Fix Mesa OpenGL detection on Solaris 11 when the NVIDIA binary blob is installed but using Mesa - phodevi: Don't report 'blkdev' on Solaris 11 as a disk drive - phodevi: Change GPU caching to allow overclocked speeds to show without rebooting - phodevi: Better support xf86-video-ati DDX driver detection in X Server fall-back mode - system_monitor: Fix for running same test multiple times when system_moitor module is loaded - pts_Graph: Improve key rendering Phoronix Test Suite 3.6 Milestone 2 7 November 2011 - pts-core: When the PHP version in use changes, re-run the recommended/required PHP checks - pts-core: Improve short SHA1 detection for results tracker - pts-core: Report notice when no OpenBenchmarking.org repository index is present and fails to fetch - pts-core: Improve Internet connectivity detection check - pts-core: When reporting a command error, report the most appropriate command name string - pts-core: Begin work on custom error handler for generated errors in code itself - pts-core: Add initial support for internal pts-core warning/notice/error handler - pts-core: Initialize the network support earlier in the client initialization process - pts-core: When running a test and saving results, show recently saved test results - phodevi: When QEMU virtualization is detected, try to report QEMU version to system layer - phodevi: Support for reporting the XOP, FMA3, and FMA4 instruction sets - phodevi: Begin merging is_genuine() support from Openbenchmarking.org into respective Phodevi components - phodevi: Improve Catalyst OpenGL driver detection with soon-to-be-released versions - phodevi: Improve GNOME version detection when using GNOME3 fall-back mode - pts_Graph: Allow normalized numbers to appear in the result file table - pts_Graph: When too many lines are being plotted, auto-convert to scalar - bilde_renderer: Improve automated color selection/shifting Phoronix Test Suite 3.6 Milestone 1 20 October 2011 - pts-core: Code clean-ups - pts-core: Allow results to be rendered in reverse order - pts-core: Add detailed-system-info command for reporting more system attributes - pts-core: Fix regression of NO_EXTERNAL_DEPENDENCIES and NO_PHODEVI_CACHE not working - pts-core: Add dump-openbenchmarking-indexes option for debugging - pts-core: Fix for extract-from-result-file not correctly formatting the new saved results name - phodevi: No longer report if CPU power savings (CnQ, EIST, etc) is active since it's now widespread across all desktop hardware - phodevi: Improve detection of low RAM capacities (1GB) - phodevi: Add support for detecting greater CPU features - phodevi: Improve system memory detection on Solaris/Illumos operating systems - phodevi: Improve disk device detection on Solaris/Illumos operating systems - phodevi: Ensure no words in motherboard identifier string are repeated - phodevi: Don't print lspci errors - phodevi: Few string reporting tweaks found from AMD Bulldozer FX system - phodevi: Virtualization detection support for Xen DomU guests - phodevi: Detect VirtualBox version from guest VM - phodevi: Expose a cpu.power sensor that provides monitoring of CPU power consumption (new feature to AMD 15h Bulldozer CPUs) - phodevi: Convert CPU model strings like 'Intel Core i7 M 620' to 'Intel Core i7 620M' to better reflect Intel product marketing names - phodevi: Basic ICC detection - phodevi: Improvements to LLVM/Clang version detection and code revision reporting - pts_Graph: Allow disconnected lines of results on line graphs - pts_Graph: Plot entire lines of data on line graphs when there are no identifiers - pts_Graph: Fix for the averages on line graphs not appearing - toggle_screensaver: Support for toggling the GNOME3 AC display settings Phoronix Test Suite 3.4.0-Lillesand 8 September 2011 - pts-core: Download the SHA1 package hash for test profiles/suites when fetching the test itself rather than using repo index - pts-core: Don't produce an error when open_basedir is in use by the PHP binary running the Phoronix Test Suite - pts-core: Fix compacting of large multi-way comparisons for compacted systems table view - system_monitor: Don't log negative values - pts_Graph: Fix key length detection for the heat-map bar graph Phoronix Test Suite 3.4 Milestone 3 31 August 2011 - pts-core: Support pts_compression library using the old ZIP API when ZipArchive is not present - pts-core: Support calling external unzip command if ZIP / ZipArchive API calls fail - pts-core: Add upload-test-profile command to upload user test profiles to their OpenBenchmarking.org account - pts-core: Add upload-test-suite command to upload user test suites to their OpenBenchmarking.org account - pts-core: When running a newer version of the Phoronix Test Suite then last time, update the OpenBenchmarking index cache - pts-core: Add openbenchmarking-repositories command to list basic information about linked OpenBenchmarking.org repos - pts-core: Support for reading the estimated run-time of test profiles from OpenBenchmarking.org repo indexes - pts-core: Support more of the non-SVG graph types within the PTS Results Viewer - pts-core: Report hardware/software information before running any test - phodevi: Improve CPU core detection; fixes detection for some ARM devices like HP TouchPad - phodevi: Improve disk storage detection for mobile devices - phodevi: Use thermal_zone0 as system temperature if it's not claimed by anything else - phodevi: Improve memory capacity detection - toggle-screensaver: Support toggling the GNOME 3.x screensaver using GSettings - bilde_renderer: Improve detection of web browsers that support SVG and those that need to fall back to PNG - bilde_renderer: Rewrite the fake ->draw_dashed_line() function to be more efficient and accurate - bilde_renderer: Improve the PNG back-end to render more closely to SVG back-end - pts_Graph: Add new system table to use on featured comparisons - pts_Graph: Introduce new horizontal box plot graph for line graphs where there's too many lines Phoronix Test Suite 3.4 Milestone 2 15 August 2011 - pts-core: Result parser fix that caused the parser to properly detect the results in some scenarios - pts-core: Dynamically build all static lists into a new PT2SO temp file - pts-core: Various code cleaning - phodevi: Various code cleaning - phodevi: Support finding Linux PCI audio devices - phodevi: Report network adapters to system hardware area - phodevi: Report virtualization platform to system layer field - phodevi: Improved file-system detection for niche file-systems - documentation: Take greater advantage of the information that can now be automatically pulled from pts-core Phoronix Test Suite 3.4 Milestone 1 19 July 2011 - pts-core: Various code clean-ups - pts-core: Add numeric check to the results parser on bar graphs - pts-core: Report valid module user commands when querying a module via module-info - pts-core: Fix SKIP_TESTS handling - pts_Graph: Various tweaks - pts_Graph: Introduce radar / spider overview graph - matisk: Commit initial module - documentation: Report valid module user commands to the HTML / PDF documentation - phodevi: Initial support for GNU Hurd operating system (tested on latest Debian GNU Hurd Wheezy snapshot) Phoronix Test Suite 3.2.1-Grimstad 29 June 2011 - pts-core: Fix regression in evaluating browser opening - pts-core: Fix browser launching on Microsoft Windows platforms - phodevi: USB Watts Up Power Meter support - system_monitor: Report sensors to be logged prior to test execution Phoronix Test Suite 3.2-Grimstad 15 June 2011 - pts-core: Moscow fixes - pts-core: Relax the requirements for appended short SHA1 identifiers in determining trackers (request by Wine/CodeWeavers) - pts-core: Add warning messages when test profile/suite data is empty due to no OpenBenchmarking.org communication - phodevi: PathCC / PathScale Compiler Suite detection - phodevi: For audio adapter try to find motherboard audio adapter or sound card rather than GPU integrated audio - phoromatic: Restore compatibility with current (old) Phoromatic.com implementation Phoronix Test Suite 3.2 Milestone 4 1 June 2011 - pts-core: Don't confuse changed hardware as being part of a results tracker - pts-core: Interactive mode improvements for Moscow - pts-core: Allow unordered multi-way comparisons - pts-core: Detect short SHA1 hashes at the end of the identifier string as being part of a results tracker - pts-core: Rework pts_bypass class into pts_flags - pts-core: Rename SKIP_EXTERNAL_DEPENDENCIES_CHECK to NO_EXTERNAL_DEPENDENCIES - pts-core: Add AlwaysUploadResultsToOpenBenchmarking option to user-config.xml - pts-core: Restore support for just passing the test profile base name to SKIP_TESTS environmental variable - pts-core: Report average value of line graphs to terminal for concise display mode - phodevi: Intel GMCH thermal monitoring sensor - phodevi: Support monitoring the GPU power consumption on Intel hardware using the gpu.power sensor - phodevi: Support determing Intel GPU load via number of commands processed per second - phodevi: Support for unity-2d desktop version detection (normal Unity has already been supported) - phodevi: Support for gnome-shell desktop version detection - documentation: Move out the auto-generated PDF documentation (it will be on web server) and just leave in the HTML documentation in tree at the request of Debian packager Phoronix Test Suite 3.2 Milestone 3 18 May 2011 - pts-core: Rework test install path handling - pts-core: Finish eliminating XML-based definitions - pts-core: Increase PHP compatibility - pts-core: Facebook HipHop should now fully work with the PTS client - pts-core: Support real-time monitoring the Nouveau GPU frequency via the gpu.freq call as exposed by system_monitor module - pts-core: Begin improving the auto-generated result file descriptions - phodevi: Internal clean-ups - phodevi: Recognition support for GPFS file-system - phodevi: Intel SNB frequency reporting - documentation: Begin auto-generation of HTML documentation in a single file that's the same content as the PDF user guide Phoronix Test Suite 3.2 Milestone 2 28 April 2011 - pts-core: Interactive mode improvements - pts-core: Add TEST_RESULTS_DESCRIPTION environmental variable support - pts-core: Add RemoveTestInstallOnCompletion to user-config.xml options - bilde_renderer: Fix for assigning the same color from a color name-space cache multiple times - phodevi: Add support for optionally reading motherboard/system serial number for Moscow - phodevi: Use PHODEVI_SMART_CACHE on display server/driver Phoronix Test Suite 3.2 Milestone 1 20 April 2011 - pts-core: Add support for EXTERNAL_PHODEVI_CACHE to load an external Phodevi cache (e.g. within Wine) - pts-core: Add support for reporting Wine version to the software system layer - pts-core: Fix for PhoroScript interpreter not running some test profiles under Wine - pts-core: OpenSUSE external dependencies updates - pts-core: Drop support for importing module-settings from pre-PTS-2.6 installations - pts-core: Support OS/distro-specific user-config XML templates - pts-core: Add IndexCacheTTL OpenBenchmarking.org option for controlling how many days before refreshing index caches - pts-core: Fix for using TEST_RESULTS_NAME environmental variable - pts-core: Consider Git SHA1 hash tags as being part of a tracker, just not dates - pts-core: Fix Debian package generation - pts-core: A text-driven interactive mode - pts-core: Support caching OpenBenchmarking.org files in /var/cache/phoronix-test-suite/openbenchmarking.org/ - pts-core: Add download-test-files command back to the Phoronix Test Suite - pts-core: Fix install-dependencies command when not being run as root - pts-core: When network connection not available / disabled, only list test/suites where OpenBenchmarking.org cache exists - phodevi: Don't confuse GCC with LLVM when sym-linking one to the other - phodevi: Better detection of Nouveau GPU thermal sensors - phodevi: Support monitoring the CPU temperature from the k10temp hwmon module - phodevi: Fix system_profiler parsing on Mac OS X 10.7 Lion ("Of" references changed to "of" in Lion) Phoronix Test Suite 3.0.1 15 March 2011 - pts-core: Restore make-download-cache option and port to PTS3 architecture - pts-core: Avoid PHP warning when cache share restoration fails - pts-core: Ensure all rows in system tables are condensed where possible - pts-core: Don't break dates into multi-way comparisons - pts-core: Fix for specifying absolute repository/[suite|test] such as for local tests - pts_Graph: Support multiple identifier lines (delimited by ' - ') on multi-way comparisons with horizontal bar graph - phodevi: Ensure Apple is reported as the manufacturer on Mac computers Phoronix Test Suite 3.0-Iveland 26 February 2011 - pts-core: When creating a lock, verify the directory is writable - pts-core: When running a result file, don't overwrite the description - pts-core: External dependencies support for Scientific Linux - pts-core: Fix for handling PRESET_OPTIONS - documentation: Final update Phoronix Test Suite 3.0 Release Candidate 2 23 February 2011 - pts-core: Drop dead code of the integrated external results hook since it's still in the result_notifier module with Iveland - pts-core: Various small fixes and tweaks - result_notifier: Last minute improvements Phoronix Test Suite 3.0 Release Candidate 1 14 February 2011 - pts-core: Read support for OpenBenchmarking.org user account client settings - pts-core: Really fix build-suite this time for writing correct suite-definition.xml files - pts-core: Support printing OpenBenchmarking.org error messages when result cloning fails - pts-core: Don't require space after colon on multi-way comparisons - pts-core: Use new code path for requesting and updating GSID from OpenBenchmarking.org - pts-core: Rename openbenchmarking-setup command to openbenchmarking-login - pts-core: Fix show-results command not actually showing the results in the PTS Results Viewer - pts-core: Check for required PHP functions/extensions earlier on in start-up process - pts-core: Allow the Phoronix Test Suite to run within Wine - pts-core: Fix normalizing result values when the result proportion is LIB - pts-core: Be more liberal in evaluating multi-way tracking to accomodate extra characters - pts-core: More efficient merging of test result objects in result file - pts-core: Minor performance optimizations along graph rendering paths - system_monitor: Fix API breakage in system monitor module - system_monitor: Better handling of used arguments collection - result_notifier: Add Intel result_notifier module - pts_Graph: Begin work on scatter plot graphing support with optional trend/linear regression line - pts_Graph: Add pts_HeatMapBarGraph type - pts_Graph: Increase width on tables when the title header is longer than the width of the table columns - bilde_renderer: Begin work on supporting gradients for the SVG renderer - bilde_renderer: Initial shading, color gradient support - bilde_renderer: Initial HSL color support - phodevi: Support for detecting Ubuntu's Unity desktop - phodevi: Fallback to reading BIOS information when Intel development motherboards don't report any motherboard information Phoronix Test Suite 3.0 Beta 4 2 February 2011 - pts-core: Only prompt to upload system logs if there are logs available - pts-core: Revert to older pts_strings::trim_spaces as the new method causes bad issues in some magical conditions - pts-core: Fix build-suite writing invalid suite definitions - pts-core: Fix ~/.phoronix-test-suite/download-cache/ not being recognized as a download cache Phoronix Test Suite 3.0 Beta 3 27 January 2011 - pts-core: Support for uploading system logs with test results to OpenBenchmarking.org - pts-core: Add user-config.xml option for always attaching system logs to test results on uploading to OpenBenchmarking.org - pts-core: Prompt user whether to attach system logs when uploading results to OpenBenchmarking.org - pts-core: When anonymous hardware reporting is enabled, additionally report select information from the PCI bus - pts-core: When anonymous hardware reporting is enabled, additionally report select information from the USB bus - phodevi: File-system detection support for KQ Infotech's ZFS on Linux - phodevi: Open64 compiler detection support - phodevi: TCC / Tiny C Compiler detection support - phodevi: PCC / Portable C Compiler detection support Phoronix Test Suite 3.0 Beta 2 19 January 2011 - pts-core: Upgrade the .openbenchmarking file support, allows multiple tests/results to be compared - pts-core: Rewrite result file CSV output - pts-core: Add openbenchmarking-refresh command - pts-core: Don't keep increasing the run count when the test is failing more than half the time - pts-core: Fix identifier case issue from OpenBenchmarking.org - pts-core: Allow the result buffer to be normalized relative to the other contained results - pts-core: Don't use OpenSSL HTTPS on non-Linux systems since it's breaking at least under OpenIndiana - pts-core: Support @ sign in test result identifiers - pts-core: Support for logging into OpenBenchmarking.org accounts via openbenchmarking-setup - pts-core: Changes to the user-config.xml specification - pts-core: OpenSUSE external dependencies update against openSUSE 11.4 - phodevi: Don't report disks that are removable - nye_Xml: Support for reading the test-definition.xml directly from an OpenBenchmarking.org test profile ZIP package - bilde_renderer: Support stuffing grouped array point pairs to draw_polygon() rather than linearly listing them - pts_Graph: Add pts_FilledLineGraph object for providing a filled line graph with combined values Phoronix Test Suite 3.0 Beta 1 10 January 2011 - pts-core: Fixes for using the local test profile/suite repository - pts-core: More minor performance optimizations along common OpenBenchmarking.org code paths - pts-core: External dependencies support for Amazon Linux AMI on EC2 Cloud Service - pts-core: Fix crashes when using build-suite and result-file-to-suite commands - pts-core: Fix for list-installed-tests command not listing any installed tests - pts_Graph: Underlying fixes for OpenBenchmarking.org - pts_Graph: Properly align background dashed lines - pts_Graph: Fix divide by zero error on rare cases of inserting zeros to maintain ordering index - phodevi: Improve NVIDIA GPU model detection when missing glxinfo - phodevi: Append Gallium3D version number to OpenGL string - phodevi: Ensure more accurate GPU name reporting than codenames when using Gallum3D drivers - phodevi: More robust motherboard detection on different sysfs nodes - phodevi: BSD hardware detection improvements (tested on DragonflyBSD 2.9-DEVELOPMENT) - phodevi: Detection support for other file-systems via their super blocks (OpenAFS, CIFS, SSHFS, etc) - phodevi: Support for reading NVIDIA core/memory clock speeds from the Nouveau driver when using latest DRM with performance levels - phodevi: Support for GPU core thermal monitoring when using the recent Nouveau DRM driver - phodevi: Support for reading VRAM capacity with TTM drivers when the kernel sysfs debug interface is enabled Phoronix Test Suite 3.0 Alpha 5 27 December 2010 - pts-core: OpenBenchmarking.org result upload fixes under select conditions - pts-core: Add support for cloning/grabbing test results from OpenBenchmarking.org - pts-core: Fix uninitialized pts_result_file_writer on using finish-run command - pts-core: Change more Phoronix Global references to OpenBenchmarking.org - pts-core: OpenBenchmarking.org launcher support by passing the .openbenchmarking file as the argument - pts-core: OpenBenchmarking.org MIME support - pts-core: Support specifying multple OpenBenchmarking.org IDs to the clone-result command and the results will then be merged - pts-core: Improve error output when a command doesn't have the necessary arguments rather than using pre-defined user error strings - pts-core: Don't force loading uninstalled tests from a virtual suite into the pts_test_run_manager - phodevi: Support appending the Catalyst driver version when the fglrx display driver is loaded - pts_Graph: With result tables, highlight not only the best values, but the worst values too - pts_Graph: Support headers/titles on pts_Table objects - pts_Graph: Support hot-switching between graphs and tables - bilde_renderer: Blacklist unsupported SVG browsers rather than whitelist supported ones, should be saner this way - bilde_renderer: Interactive API clean-up Phoronix Test Suite 3.0 Alpha 4 14 December 2010 - pts-core: Drop support for reference-comparison as its superseded by OpenBenchmarking.org implementation - pts-core: TEST PROFILE XML SPEC CHANGE: EstimatedLength -> EstimatedTimePerRun - pts-core: Further work on OpenBenchmarking.org-supported validate-test-profile command - pts-core: Support new test identifier syntax from OpenBenchmarking.org - pts-core: Support for uploading test results to OpenBenchmarking.org - pts-core: Add a local repository for test profiles and test suites that aren't on OpenBenchmarking.org - pts-core: Restore support for virtual suites using a new design that is supportive of OpenBenchmarking.org architecture - pts-core: Add list-available-virtual-suites command - pts-core: Begin revamping the Phoronix Test Suite documentation, add PDF documentation - pts-core: Improve validation of tests to run in queue, do so earlier in process - pts-core: Auto-generate the man page from the new documentation system - pts-core: Auto-generate the help command from the new documentation system - phodevi: Improved hardware/software string reporting - phodevi: More concise GPU string reporting - pts: Move test profiles out of the phoronix-test-suite client and into the OpenBenchmarking.org cloud - pts: Move test suites out of the phoronix-test-suite client and into the OpenBenchmarking.org cloud Phoronix Test Suite 3.0 Alpha 3 2 December 2010 - pts-core: Fix test suites failing to run where it'd get caught in an infinite loop - pts-core: Fix for suite support on Iveland - pts-core: Add ReferenceID tag to result-file specification - pts-core: Support for remote download caches on test installation without relying upon pts-install.xml index - pts-core: Add SaveTestLogs to user-config.xml for now toggling whether to save the test logs - pts-core: Add an XML Schema XSD covering the result-file - pts-core: Add an XML Schema XSD covering the test-suite - pts-core: Add an XML Schema XSD covering the test-profile-downloads - pts-core: Add an XML Schema XSD covering the results-parser - pts-core: Add an XML Schema XSD covering the test-profile - pts-core: On client program startup, report any missing PHP extensions that are required or recommended - pts-core: TEST PROFILE XML SPEC CHANGE: TestInformation/Version -> TestInformation/AppVersion - pts-core: TEST PROFILE/SUITE XML SPEC CHANGE: Split RequiresCoreVersion tag into RequiresCoreVersionMin and RequiresCoreVersionMax - pts-core: Add InternalTags to XML test profile schema - pts-core: Drop support for ~/pts-test-note as the capabilities are now found within InternalTags using a cleaner method - pts-core: Better the support for Illumos OpenIndiana b147 - pts-core: Support still saving test results when using the system_monitor module even when all tests being run are of NO_RESULT type - phodevi: Few Mac OS X support improvements - phodevi: Support NVIDIA GPU core usage monitoring via nvidia-smi - phoromatic: HTTPS connection support, install the Phoromatic.com SSL certificate - pts: Update apache test profile against upstream Apache 2.2.17 - pts: Update build-apache test profile against upstream Apache 2.2.17 - pts: Update build-mplayer test profile against upstream MPlayer 1.0rc3 - pts: Update compress-7zip test profile against upstream p7zip 9.13 - pts: Update ffmpeg test profile against upstream FFmpeg 0.6.1 - pts: Update graphics-magick test profile against GraphicsMagick 1.3.12 - pts: Update pgbench test profile against PostgreSQL 9.0.1 - pts: Update sqlite test profile against SQLite 3.7.3 - pts: Update x264 test profile against upstream x264 2010-11-22 - pts: Update ramspeed test profile against RAMspeed SMP (RAMSMP) 3.5.0 - pts: Add the CLOMP OpenMP LLNL benchmark - pts: First pass at validating all test profiles - pts: Verify each upstream test profile's compatibility on Solaris, BSD, and MacOSX Phoronix Test Suite 3.0 Alpha 2 18 November 2010 - pts-core: THE RESULT FILE XML SCHEMA HAS CHANGED. PTS-CORE SHOULD AUTOMATICALLY BE BACKWARDS-COMPATIBLE IN READING OLD XML FILES, BUT IF YOU EXTERNALLY ACCESS THIS XML DATA IT WILL NEED TO BE UPDATED. - pts-core: Add the OpenBenchmarking.org HTTPS certificate - pts-core: Replace tandem_XmlReader with nye_XmlReader as a new PTS DOM-based XML parser - pts-core: Replace tandem_XmlWriter with nye_XmlWriter as a new PTS DOM-based XML parser - pts-core: Fix external dependency installation on Debian proper - pts-core: Make the systems table actually render nicely - pts-core: Support for OpenIndiana b147 - bilde_renderer: Begin work on a new DOM-based back-end renderer that will eventually form the new rendering interface; currently it's producing suitable SVG - pts: Add initial support for the Angstrom (OpenEmbedded) Linux distribution with external dependencies - pts_Graph: Add SVGZ renderer back-end that Gzip compresses the SVG renderer output - pts_Graph: Various improvements Phoronix Test Suite 3.0 Alpha 1 9 November 2010 - pts-core: Split part of pts_test_profile into pts_test_profile_parser as the lighter-weight profile parsing parent for use where applicable - pts-core: Drop option support for required_function_sets as everything is now modularized to objects - pts-core: Rename AllowGlobalUploads tag in the test profile specification to AllowResultsSharing - pts-core: Drop P_RESULTS_SUITE_TYPE, P_RESULTS_SUITE_NAME, P_RESULTS_SUITE_VERSION from the results specification - pts-core: Fix external dependency installation on OpenSUSE when using Zypper - pts-core: Eliminate "base-test-[profiles,resources]" but for PTS3 they need to all be integrated to a single location - pts-core: No longer support test profile scripts as PHP files but require them to be SH files - pts-core: Rename parse-results.xml to results-definition.xml - pts-core: More aggressive checks in determining whether to dynamically increase the run count for statistical accuracy - pts-core: Allow the sys.time monitor command to work on PHP installations where PCNTL is not supported or available - pts-core: When installing test dependencies, double check the depdendencies were installed otherwise prompt the user what to do - pts-core: Temporarily drop the GTK2 GUI until it's been rewritten to be compliant with the PTS3 architecture - pts-core: Drop PTS assignments as everything is now worked into object properties or otherwise factored out - pts-core: THE FILE STRUCTURE OF ALL TEST PROFILES HAS NOW CHANGED - pts-core: Drop make-download-cache command since it will end up not being needed with PTS3 - pts-core: Add external hooks to the PTS3 user-config.xml for PreTestProcess, InterimTestProcess, and PostTestProcess - pts_Graph: Introduce Iveland horizontal bar graphs - pts_Graph: Default to using the SVG bilde_renderer back-end when no other renderer is specified, affects new setups - install-sh: Installer updates - pts: Restructure test profiles - pts: Add nginx test profile as a new NGINX web-server benchmark similar to the apache test profile Phoronix Test Suite 2.8.1 September 9, 2010 - pts-core: Fix a regression that caused alpha-numeric PTS module option values to fail - pts-core: During the testing process, set the vblank_mode environmental variable to 0 by default - pts-core: Fix/enhance pie chart rendering of result data Phoronix Test Suite 2.8 "Torsken" August 31, 2010 - pts-core: Support for detecting multiple compilers - pts-core: Allow the system_monitor module to provide independent graphs for each test result - pts-core: Warn the user when PHP POSIX is needed and it's not present - pts-core: When doing a multi-way comparison with line graphs, average the results and convert to bar graphs - pts-core: Fix test result failing to parse when using LineBeforeHint in pts_test_result_parser Phoronix Test Suite 2.8 Beta 3 August 24, 2010 - pts-core: When the NVIDIA driver is loaded, better recognize when the GPU is overclocked by the user - pts-core: Unless a test is using an integrated timer, it must specify a parse-results.xml file even if the log file is just the result to be parsed - pts-core: Provide clean system monitoring capabilities through the parse-results.xml interface - pts-core: Replace TIMER_START and TIMER_STOP integrated timer functionality by exposing sys.time in the results parsing interface - pts-core: Transition pts_result_file_result object to using pts_test_result - pts-core: Transition pts_test_run_request to use the pts_test_result object - pts-core: Improve external dependency handling on unsupported operating systems / distributions - pts-core: Try to avoid using Konqueror for displaying test results as its bad with XSL - pts-core: Drop analyze-result-file command since its capabilities are to be in the PTS Results Viewer itself - pts: Add juliagpu OpenCL test - pts: Add mandelgpu OpenCL test - pts: Add smallpt-gpu OpenCL test - pts: Add mandelbulbgpu OpenCL test - pts: Add opencl test suite - pts: Update dead download links in several test profiles - documentation: Add note that PHP PCNTL support is required now for many tests Phoronix Test Suite 2.8 Beta 2 August 18, 2010 - pts-core: Fix regression in analyze-batch that led to producing unexpected results - pts-core: GTK2 GUI regression fixes - pts-core: Various core regression fixes - pts-core: Clean out parts of the API that are redundant and will be with PTS3 - pts-core: Automatically increase the test run count if at least one test run successfully ran, but at least one test run failed - pts-core: Add lib3ds external dependency for providing AutoDesk 3DS file support - pts-core: Add gmp-library external dependency for providing the GNU Multiple Precision Arithmetic Library - pts-core: Fix for a smaller panel resolution being reported when using NVIDIA's TwinView - pts: Update build-imagemagick test profile due to old download links that failed, now at ImageMagick 6.6.3 - pts: Add smallpt test profile as a lightweight, multi-threaded path tracing benchmark - pts: Add gluxmark test profile for the gluxMark OpenGL 3.2 / OpenCL benchmark Phoronix Test Suite 2.8 Beta 1 August 3, 2010 - pts-core: Report the standard error of test results within the result table - pts-core: When the run count is dynamically increased (likely due to std dev being too high), report the std dev to the concise display mode - pts-core: Reinstantiate the pts_client display when calling the run or install process so the debug display mode can be loaded if needed - pts-core: Drop install-all-dependencies option as running "install-dependencies all" has been the recommended way - pts-core: Rewritten PTS External Dependency implementation - pts-core: Rewritten PTS test installation code - pts-core: Drop PossiblePaths XML tag for test profiles as it is no longer used by any upstream test profiles - pts-core: Add "overview graph" to the PTS Results Viewer - pts-core: Add LineAfterHint to parse-results.xml interface for indicating a line after the test results line that's wanted - pts-core: Add Message tag to test profile XML specification for pairing it with a of a menu option for providing additional information to user - pts: Update crafty test profile against Crafty 23.3 - pts: Update openssl test profile against OpenSSL 1.0.0a and add Windows support - pts: Add systester test profile as a new CPU test Phoronix Test Suite 2.8 Alpha 2 July 22, 2010 - pts-core: Fix recover-run command always reporting the system software has changed, regression from first alpha - pts-core: More underlying PTS3 changes - pts-core: Add SKIP_EXTERNAL_DEPENDENCIES_CHECK environmental variable for skipping the PTS external dependency checking on test install - pts-core: Add rebuild-composite-xml option for rebuilding the composite.xml file in a result file - pts-core: Fix parse-results.xml MultiMatch not working from a regression in 2.8a1 - pts-core: When installing test dependencies, don't confuse the root user if the user is connected to a Phoronix Global account - pts-core: No longer rely on passing around $display_mode but utilize pts_client::$display for displaying user I/O - phodevi: Nouveau detection improvements for when the X Server isn't running - pts: Update vdrift and vdrift-fps-monitor test profiles against VDrift 2010-06-30 Phoronix Test Suite 2.8 Alpha 1 June 30, 2010 - pts-core: Start work on pts_PieChart for generating pie charts - pts-core: When installing/running a test, make sure the TEST_ENV_DIR is writable - pts-core: Add MultiMatch support to the parse-results.xml interface - pts-core: Don't add empty tests to the test execution queue - pts-core: Don't delete old test results when running a saved test result identifier and it fails - pts-core: Don't report test profiles with a NO_RESULT ResultFormat as having failed to run - pts-core: Drop support for parse-results.php/parse-results.sh, now mandate the parse-results.xml interface as its superior - pts-core: Add FORCE_MIN_TIMES_TO_RUN environmental variable support - pts-core: Attempt to better determine inverted multi-way comparisons - pts-core: Validate test installations to run prior to save prompt - pts-core: Further tweaking of the PTS Results Viewer - pts-core: Drop analyze-linear-tracker command as we now auto-determine whether the result file is a tracker-type test - pts-core: Ensure unique color indexes where possible on rendered graph keys - pts-core: Lots of internal code changes for PTS3 plans - phodevi: When LLVMpipe is being used, support modes below 800 x 600 - pts: Drop fgl-glxgears, fract, md-gromacs, memory-bandwidth, super-pi test profiles - pts: Update mplayer-base with newer MPlayer snapshot and add VA-API support - pts: Update video-cpu-usage test profile to use Big Buck Bunny 1080p H.264 sample Phoronix Test Suite 2.6.1 June 3, 2010 - pts-core: External dependencies support for MeeGo - pts-core: Fix for running merge-results command with un-cloned Phoronix Global IDs - pts-core: Fix for the system monitoring test library to reflect recent Phodevi sensor API changes - pts-core: Fix for crammed values under certain scenarios in pts_Graph - pts-core: Support for reporting installed software / hardware statistics - pts-core: Fix misaligning some pts_Chart result values when test results are missing for a run - pts: Update unigine-heaven test profile to Unigine Heaven 2.1 - pts: Update unigine-sanctuary test profile to Unigine Sanctuary 2.3 - pts: Update unigine-tropics test profile to Unigine Tropics 1.3 Phoronix Test Suite 2.6 "Lyngen" May 24, 2010 - pts-core: When using the finish-run command and finishing the run doesn't complete any new tests, don't delete the results - pts-core: Allow multiple identifiers to be specified with the GRAPH_HIGHLIGHT environmental variable - pts-core: Report failed test installations for conditions beyond files missing and non-zero exit statuses - phoromatic: Allow the Phoromatic client to run a set-context script when told to do so by Phoromatic server - pts: Add ttsiod-renderer as an OpenMP, entirely CPU/software driven 3D renderer - pts: Update broken download links Phoronix Test Suite 2.6 Beta 3 May 13, 2010 - pts-core: More PTS Results Viewer improvements - pts-core: Support line graphs in charts - pts-core: Smarter rendering layout of the pts_Graph keys - pts-core: Add copy-run-in-result-file option - pts-core: Client tracker improvements - pts-core: Auto detection of result identifiers to determine if tracker-type testing and apply optimizations if so - phodevi: Rework entire Phodevi sensor API/architecture - phodevi: Add support for monitoring the GPU fence count Phoronix Test Suite 2.6 Beta 2 May 6, 2010 - pts-core: Don't report a test run as failing if you don't save the test results - pts-core: Show the individualized results table within the web results viewer - pts-core: Report the difference and standardized deviation to individualized result tables - pts-core: Various results viewer improvements - pts_Graph: Support for a universal color table - pts_Graph: Add GRAPH_COLOR_GROUP_SIMILAR - pts_Graph: Chart improvements - pts_Graph: Don't plot points that are bound to the right wall on the line graph - pts: Add network-loopback test profile - pts: Add phpbench test profile - pts: Update iozone test profile and provide Windows support Phoronix Test Suite 2.6 Beta 1 April 26, 2010 - pts-core: Add ResultBeforeString tag to parse-results.xml interface - pts-core: When a filesize is not supplied by downloads.xml, try to calculate it using filesize() if applicable - pts-core: Don't bold the pts_Chart results "winners" when there is only one test run - pts-core: New PTS Results Viewer interface - pts-core: Add generated section to PTS result file XML - pts-core: Many PhoroScript interpreter improvements - pts-core: Add run-tests-in-suite option for running tests in a suite, but using user-defined settings - pts-core: Remove install-all and force-install-all options as they have been deprecated since PTS 1.6, use the "all" virtual suite instead - pts-core: Fix when running the same test identifier for a result file multiple times and its test log dir has rename problem - pts-core: Add GRAPH_HIGHLIGHT environmental variable for highlighting specific test results when rendering a graph (initially for bar graphs) - pts-core: Add total_testing_time to the core storage that keeps track of how much time the given system spends benchmarking forever - phodevi: Improve system thermal monitoring sysfs nodes on Linux - phodevi: Improve Clang/LLVM compiler detection - phodevi: Add DEFAULT_VIDEO_MODE environmental variable - pts: Add compiler suite - pts: Update crafty test profile against Crafty 23.2 - pts: Update smokin-guns test profile against Smokin' Guns 1.1 Beta 4 - pts: Start porting over numerous test profiles to offer Windows 7 x64 compatibility Phoronix Test Suite 2.6 Alpha 3 April 12, 2010 - pts-core: If the NO_MD5_CHECKS environmental variable is set, don't perform MD5 file checks on test installation - pts-core: Don't install the linux-32bit-libraries external dependency by default on 64-bit Linux systems - pts-core: Fix length of download text progress indicator - pts-core: Fix regression that caused the merge-results option not to work - pts-core: Graphing tweaks - pts-core: Add suite-to-pdf option - pts-core: Restore compatibility for the Phoronix Test Suite on PHP 5.1 and early PHP 5.2 versions - pts-core: Installation error string improvements - pts-core: Run-time string improvements - pts-core: Rework environmental variables handling - pts-core: Various fixes - phodevi: Fix causing a segmentation fault on some Mesa systems - pts: Update unigine-heaven test profile against Unigine Heaven 2.0 - pts: Update openssl test profile against OpenSSL 1.0.0 upstream Phoronix Test Suite 2.6 Alpha 2 March 20, 2010 - pts-core: Add /tmp/phoronix-test-suite.active lock - pts-core: Move module define statements out to using the PTS definitions XML - pts-core: Optimizations for Phoromatic Tracker - pts-core: New module settings configuration store - pts-core: Add support for passing PTS module setup options via an environmental variable to PTS_MODULE_SETUP - pts-core: Expand the capabilities of the parse-results.xml interface - pts-core: Add image quality comparison support to the parse-results.xml interface - pts-core: Add support for harmonic means for Phoromatic Tracker - pts-core: Consolidate pts_Graph configuration setup - pts-core: Consolidate user configuration setup - pts-core: Rewrite and make working pts_Chart - pts-core: Add more files/commands to log for the system logs - pts-core: Faster, more efficient rendering of graphs - phoromatic: When setting up the Phoromatic module, allow the system description to be inputted and then sent to the Phoromatic Server - phodevi: Support for Clang compiler - phodevi: Quirk handling for PCLinuxOS as it doesn't know how to properly identify itself - phodevi: Support for reading the default and current GPU/memory frequencies with ATI Radeon KMS power management on Linux - phodevi: Update system memory sensor - pts: Add xplane9-iqc test profile for image quality comparison tests on X-Plane 9 - pts: Drop compliance-ogl test profile Phoronix Test Suite 2.6 Alpha 1 March 9, 2010 - pts-core: No longer statically code define statements for XML parsing, move into pts-core/definitions XML statements - pts-core: Add EST_TIME_REMAINING variable assignment that has the estimated run-time remaining during testing - pts-core: Add RequiresCoreVersion tag to XML test suite specification similar to the test profile implementation - pts-core: Don't run graphics tests if the driver configuration is known to not support 3D acceleration at all - pts-core: Temporarily drop support for PTS weighted suites until it is rearchitected - pts-core: Add new interface (parse-results.xml) for handling results parsing of tests using an XML file with a result template - pts-core: Add ProfileVersion tag to XML result file specification - pts-core: Add some of the Phoromatic Tracker helper scripts - phodevi: Add support for detecting Reiser4 file-system via its super magic block - phodevi: Report hard drive manufacturer when detected and prepend to the model string - phodevi: Add initial audio / sound card detection support - phoromatic: Add support for powering off the system if told to do so by the Phoromatic server - phoromatic: Add support for restarting the system if told to do so by the Phoromatic server - phoromatic: Wait an additional 90 seconds on connectivity problems - phoromatic: Report estimated time remaining to test completion to Phoromatic server - phoromatic: Add client support for the Phoromatic trigger interface - phoromatic: Support for reading the Phoromatic server build/version - bilde_renderer: Fi x the SVG renderer back-end from battling multiple graph style values contained in a single page - pts_Graph: Line graphing improvements for Phoromatic Tracker - pts-core: Various fixes and improvements - pts: Add adjustable record / block size to iozone test profile - pts: Remove dead download links - pts: Update openarena test profile against OpenArena 0.8.5 patch - pts: Update xplane9 test profile against XPlane 9.45 timedemo Phoronix Test Suite 2.4.1 February 18, 2010 - pts-core: Pass PTS result objects directly to pts_Graph - pts-core: Add WatermarkURL option to graph-config.xml - pts-core: Drop support for the PTS_USE_OLD_DOWNLOAD_CODE override for using the old networking code - pts-core: Faster merging of test results and pair similar tests together - pts-core: When network support is down, don't prompt to upload results to Phoronix Global - pts-core: When user fails to agree to the first-run user-agreement, don't bother asking about anonymous usage reporting - phoromatic: Add phoromatic.clone-results option for cloning test results from a Phoromatic repository, when the clone option is enabled from the server side - phoromatic: Add phoromatic.system-schedule option for seeing the system's test schedule from the Phoromatic server - phoromatic: Add phoromatic.system-schedule-today option for seeing the system's test schedule for today from the Phoromatic server - phoromatic: Add phoromatic.send-message option to send any bits of information to the Phoromatic Server to list in the system warning area for that system - phoromatic: Support for uploading test and system logs to Phoromatic server - bilde_renderer: Add initial interactivity support for on-click events with some drawing elements - toggle_screensaver: Properly stop and start the screensaver using qdbus on KDE4 - pts_BarGraph: Report standard deviation on test results when hovering over a bar with a supported renderer - pts_LineGraph: Add switch with new path for handling many identifiers in different way - pts_LineGraph: Add last values to line graph display - pts: Drop MD5 hashes in the wine-* humus tests - pts: Various small fixes - pts: Don't use parallel make jobs with encode-mp3 test profile due to Moblin build problems Phoronix Test Suite 2.4.0 February 2, 2010 - pts-core: Report to test notes area of PTS test results if the system was using eCryptfs - pts-core: Fix GTK2 GUI bug of multiple instances of the GTK2 GUI test run-time window being shown - pts-core: Support passing multiple tests/suites to download-test-files option - pts-core: Allow arguments to be passed and used by the build-suite option for specifying tests/suites - pts-core: Fix a bug that caused the basic display mode to be used on Anzhofen - pts-core: Add task-cache-reference-comparison-xml option for more easily building caches on Anzhofen - phodevi: Workaround for Radeon KMS not reporting all available modes when connected to a 2560 x 1600 panel - pts_LineGraph: When there becomes too many point identifiers to be plot (such as with Phoromatic Tracker), only plot every so often - phoromatic: Allow unscheduled test results to be uploaded to Phoromatic server, if the settings enable it - pts: Add pts-desktop-live suite for Anzhofen - pts: Add pts-netbook-live suite for Anzhofen Netbook - pts: Update out of date download links within test profiles - pts: Update page size for iozone per input from Oracle Phoronix Test Suite 2.4 Beta 3 January 25, 2010 - pts-core: When running on BSD with Linux binary compatibility loaded, download the Linux-specific files for a test too - pts-core: Better handling of missing tests - pts-core: Faster reference system comparison support - pts-core: Build reference system comparison cache when starting the GTK GUI - pts-core: Add ReferenceSystems tag to user-config.xml for specifying extra reference system comparison IDs - pts-core: Add width and height attributes to SVG graphs to show better in more web browsers with the PTS Results Viewer - pts-core: New integrated network download engine - pts-core: Add Timeout tag to the user-config.xml for adjusting the network read timeout - pts-core: Launch a network support and proxy interface when launching the GTK GUI and no Internet is detected - pts-core: Add debug-test-download-links option to find broken download links in test profiles - phodevi: Support reading the system temperature through the hwmon sysfs interface - phodevi: Fallback support to read the current monitor mode from xdpyinfo when available - phodevi: Support for reading newer version numbers of the KDE Software Compilation desktop - phodevi: Better CPU thermal monitoring - phodevi: Faster / more efficient reading of sysfs nodes - pts: Add unpack-linux test as a disk benchmark for timing how long it takes to extract the Linux kernel source - pts: Drop filesystem test suite as its similar to the disk test suite, so move all the tests there - pts: Add compilebench test profile for Oracle's Compile Bench - pts: Update many out of date download links within test profiles Phoronix Test Suite 2.4 Beta 2 January 21, 2010 - pts-core: Preserve decimal accuracy based upon result values - pts-core: Change the padding depth for the concise display mode - pts-core: If MD5 fails when copying a file from a local download cache that has been verified, try a second time - pts-core: Support specifying multiple result identifiers to extract when using extract-from-result-file - pts-core: Show the "latest run time" with the info command when reading a test - pts-core: Move result-viewer files within the static directory - pts-core: Begin reworking the code path for when running on an operating system without PTS external dependencies support - pts-core: Better support for OpenBSD - pts-core: Add "File Found" reporting to the display mode interface - pts-core: Support reading proxy settings (if not set in user-config.xml) from http_proxy environmental variable - pts-core: Various code cleaning - pts-core: Use PTS_CORE_VERSION rather than PTS_VERSION for RequiresCoreVersion tag in PTS test profile - pts-core: Don't write empty system information XML to results file - phodevi: Further fallback support for BSD graphics card detection - phodevi: Add sensor for system fan speed monitoring - phodevi: Rework screen resolution mode code - pts_Graph: Be smarter with the steps to use for the axis on the scale - bilde_renderer: Don't use any GD-based renderer if no TTF font files can be found - pts: Update download links for pgbench test profile - pts: Update server and workstation test suites Phoronix Test Suite 2.4 Beta 1 January 14, 2010 - pts-core: When using the GTK2 GUI, support handling license type for suites - pts-core: Improve reporting of empty lists and other areas - pts-core: Support reading from a remote PTS download cache via proxy - pts-core: When copying a MD5-matched file from a local PTS download cache, still verify that the MD5 of the copied file matches - pts-core: Cleanup test installation code - pts-core: Initial support for Debian's GNU/kFreeBSD - phodevi: Windows improvements - phodevi: Improve NVIDIA binary driver detection without glxinfo - phodevi: Improve Mesa/DRI driver detection without glxinfo - phodevi: Rework the screen resolution detection code for Linux/BSD/OpenSolaris code paths - phodevi: Support reading the CPU fan speed for more systems - pts: Result reporting fix for specviewperf10 test profile Phoronix Test Suite 2.4 Alpha 3 December 22, 2009 - pts-core: Overhaul pts_test_result class - pts-core: Add open_basedir php.ini setting check when starting the Phoronix Test Suite - phodevi: Add CPU fan speed sensor, currently implemented on Linux through sysfs interface - phoromatic: If initial Phoromatic server connection fails, wait 60 seconds and try again - phoromatic: If uploading of test results to Phoromatic server fails, wait 60 seconds and try again - tandem_XmlReader: Drop support for XML tag/file caching in the XML parser since now its more efficient and effective to let pts-core handle it - pts: Update ramspeed test profile against RAMspeed 2.6.0 Phoronix Test Suite 2.4 Alpha 2 December 15, 2009 - pts-core: Start work on having a panel in the GTK2 GUI for managing the PTS modules - pts-core: Add and implement PostArguments tag to test profile XML specification - pts-core: Export TEST_ as the HOME directory, similar to the variables when extending a test that are set - pts-core: Add post-cache-share script support for test profiles to optionally implement that take advantage of PTS cache shares - pts-core: Merging improvements for handling image quality comparisons, plus other safeguards merged too - pts-core: More aggressive sleep timer between tests, don't sleep before entering a PTS cache share - pts-core: Add analyze-image-delta option for carrying out delta image comparisons of test results - pts-core: Only show "Test All Options" option for tests when there is more than one option to select - pts-core: Log to the pts-install.xml how long it takes for a test to install - pts-core: Add pts-test-installation-viewer.xsl for viewing pts-install.xml files - pts-core: Support merging pts_result_file objects that also have results that need to be renamed - pts-core: Phoromatic updates - pts-core: Add analyze-linear-tracker command option - pts-core: With analyze-all-runs, refresh-graphs, and analyze-linear-tracker there is no need to reprocess the entire XML file, so be more efficient - phodevi: Clean phodevi_linux_parser::read_sys_dmi() against hal-values-remove.list - phodevi: Better handle NVIDIA's detailed OpenGL version string - phodevi: Support for detecting the X.Org vesa driver - phoromatic: Add support for the server to tell the client module whether to run the install command prior to testing (change from the web interface) - phoromatic: The Phoromatic server (through the settings area) can now tell test machines to exit PTS when testing is done for the day - bilde_renderer: Add draw_rectangle_with_border to the drawing API - bilde_renderer: Add draw_poly_line to the drawing API - bilde_renderer: Add draw_dashed_line to the drawing API - bilde_renderer: Use the BILDE_RENDERER define or environmental variable to override the renderer - bilde_renderer: Vastly improve the SVG renderer back-end, make it proper for Phoromatic usage - pts: Add vdrift-fps-monitor test profile that charts out the FPS on a line graph during the testing process - pts: Rename the iqc-nexuiz test profile to nexuiz-iqc - pts: Add etqw-demo-iqc test profile for image quality comparisons with ET: Quake Wars Demo - pts: Add iqc test suite for image quality comparison tests - pts: Begin supporting unigine-heaven test profile - pts: Overhaul the tiobench test profile - pts: Add fs-mark test profile - pts: Add daily-system-tracker test suite Phoronix Test Suite 2.4 Alpha 1 December 2, 2009 - pts-core: Change default display mode to the pts_concise_display_mode object - pts-core: Add dump-core-storage option for dumping the contents of the core.pt2so object - pts-core: Add dump-phodevi-smart-cache option for dumping the contents of the Phodevi Smart Cache from core.pt2so - pts-core: Initial Windows support for the Phoronix Test Suite; this drop is mostly the .bat launcher and initial hardware detection support - pts-core: Support loading pts-core objects deeper in the directory - pts-core: Move the PTS External Dependencies XML and scripts from pts/ into pts-core/static/ - pts-core: Move pts-core/scripts/ contents to pts-core/static/scripts/ - pts-core: Drop support for UnsupportedPlatforms tag in PTS test profile specification, tests should be using SupportedPlatforms tag - pts-core: Add support for IMAGE_COMPARISON type in ResultFormat spec of a test profile - pts-core: Add AllowGlobalUploads tag to XML test profile specification to allow a test profile to block against Phoronix Global uploads - pts-core: Add AutoSaveResults tag to XML test profile specification to allow a test profile tu automatically have the results saved without the user option - pts-core: Hook in the Phoronix Test Suite proxy support to curl and wget - pts-core: Add prev-test-identifier virtual suite of whatever the previously executed command(s) - pts-core: Add prev-save-identifier virtual suite of the previously saved identifier (if available) - pts-core: Add export-profile-package option for exporting a PTS test profile as a zip package - pts-core: Add import-profile-package option for importing a PTS test profile from a zip package - pts-core: Add support for /opt/bin/php - pts-core: Add PTS External Dependencies support for Optware - pts-core: Add yasm to PTS External Dependencies - pts-core: Support using PHP's cURL library for handling downloads when available - pts-core: Calculate download speeds for each test file download, to provide estimations on future downloads for how long it may take to download - pts-core: Drop support for SH PTS modules, since it was rarely used and just added overhead to pts-core module architecture - pts-core: Only process a PTS module API call to a module if it actually hooks into that method - pts-core: When running analyze-batch on a result file that already has line graphs, don't do funky things with the results - pts-core: PTS module architecture revisions - pts-core: Alias CC=gcc if gcc is present and cc is not - pts-core: Always save test log files, make them easily accessible from the PTS Results Viewer - pts-core: Add TEST_COUNT_PASS graph type for ResultFormat - pts-core: When running on BSD, detect if Linux compatibility support is loaded and then allow Linux-supported test profiles to run - pts-core: Add debug-install option - pts-core: Fix files not downloading when PromptForDownloadMirror is set to TRUE - pts-core: Address several PHP E_STRICT warnings - pts-core: Better alignment for the concise display mode interface - phodevi: Split out phodevi_parser module into phodevi_linux_parser, phodevi_osx_parser, and phodevi_solaris_parser for OS-specific functions - phodevi: Avoid situations of the manufacturer/vendor string being repeated in the motherboard property - phodevi: Add device notes and special settings string functionality to API - phodevi: Initial support for Palm webOS platform - phodevi: Better compiler detection support, should work better on webOS - phodevi: Add support for monitoring battery current (initially limited to the Palm Pre) - phodevi: Support reading the system temperature through the thermal sysfs interface on Linux - phodevi: Add system.iowait sensor for the system's iowait as a percentage - phodevi: Add disk-speed.read and disk-speed.write system sensors in MB/s - phodevi: Support reading the current screen resolution from the kernel DRM when using a KMS driver - phodevi: Improve NVIDIA GPU detection on BSD systems when glxinfo is not installed - phodevi: Improve BSD hard drive detection - phodevi: Support monitoring the system's battery power consumption rate on BSD - phodevi: CPU usage monitoring support for BSD - phodevi: Support monitoring the system's battery power consumption rate on OpenSolaris - phodevi: Motherboard chipset vendor detection on OpenSolaris - phoromatic: Use a locking system to prevent multiple copies of the Phoromatic module from running simultaneously - embedded: Add a PTS module named "embedded" that is a collection of options to help those running PTS on embedded/mobile devices - system_monitor: Append sensor monitoring graphs to end of result file during testing - system_monitor: Rely on sensor results to be outputted to the test results file - scp_result_pusher: Add a PTS module for pushing test results automatically to a remote destination over SCP - pts_Graph: Add pts_ImageComparisonGraph object - pts_LineGraph: Don't plot lines all the way to the end unless relevant - pts_LineGraph: Render average, peak, and low values at the top of the graph when showing percentages - pts_LineGraph: Improved plotting of points under certain conditions - pts: Add initial iqc-nexuiz test profile for image quality comparison support - pts: Add x264 test profile for x264 H.264/Y4M encoding application - pts: Add idle-power-usage test profile - pts: Add battery-power-usage test profile - pts: Add himeno test profile for the Himeno pressure solver benchmark - pts: Update mplayer-base test profile against MPlayer 2009-11-28 SVN snapshot - pts: Revert gnupg test profile to use GnuPG 1.4.9 until the proper, working GnuPG2 patches are received - pts: Add gcrypt test profile that benchmarks libgcrypt's CAMELLIA256-ECB cipher - pts: Add bullet test profile for the Bullet Physics Engine - pts: Add daily-kernel-tracker test suite Phoronix Test Suite 2.2.0 "Bardu" November 16, 2009 - pts-core: Various code path optimizations and cleaning - pts-core: Add dump-system-sensors option to display a readout of all supported Phodevi sensors and their values and print unsupported sensors - pts-core: Fix TEST_RESULTS_NAME environmental variable not working - pts-core: Fix network-setup network testing check actually use the proxy, hook in the HTTP proxy override properly - pts-core: Clean-up download cache directories code - pts-core: Add "installed-tests" virtual suite of tests that are currently installed - pts-core: On GTK2 GUI Don't show buttons/header for reference system comparisons for results when there are actually no results to compare - pts-core: Small OpenSolaris 2010.02 support updates - pts-core: Various small bug fixes - phodevi: Support for the GPU fan-speed sensor with ATI graphics driver - phodevi: Add support for reading the stock GPU engine/memory clock when using the open-source Radeon driver - phodevi: Fixed detection of the xf86-video-radeonhd display driver - phodevi: Fix throwing SUSE Linux 11.2 into an infinite loop when running "X -version" on this OS, "Xorg -version" works fine instead - pts: Update darwin test suite - pts: Support using zypper to install external dependencies on SuSE/OpenSuSE since it can ignore missing / removed packages without failing - documentation: Update documentation for Phoronix Test Suite 2.2 Phoronix Test Suite 2.2 Beta 3 November 9, 2009 - pts-core: Fix API breakage for installing dependencies from install-dependencies option call - pts-core: Report the disk scheduler to the test notes area when a disk test is run - pts-core: Add SelectSuitesOrTests tag to user-config.xml for selecting between tests / suites showing by default in GUI - pts-core: Add initial analyze-result-file command for showing basic analytical / stats for a given result file - pts-core: Support showing information from info command when supplying a virtual suite - pts-core: Don't contain tests that are of license RETAIL or RESTRICTED in the "all" virtual suite - pts-core: Fix where recover-run would not recognize the result file if there was not at least one successful one previously - pts-core: When using recover-run, put back in batch mode state if the test was originally run in batch mode - pts-core: Validate test installations earlier in the test run process - pts-core: When clicking "View Results" from GTK2 GUI, generate graphs if needed - pts-core: Fix regression that broke reference comparisons and removing identifiers from result files - phodevi: Add support for GPU fan speed monitoring (currently only implemented for NVIDIA's binary display driver) - phodevi: Add property to disk object for reading the scheduler in use - phodevi: DMI parsing support on Linux through /sys/class/dmi/id/ interface, for now implement motherboard way - phodevi: Detect and support reading the X.Org DDX driver module version for Cirrus and other obscure drivers/hardware - pts: Update for Fedora external dependencies XML - pts: Start adding new reference comparison systems with runs against Phoronix Test Suite 2.2 Phoronix Test Suite 2.2 Beta 2 November 3, 2009 - pts-core: With toggle_screensaver module, disable the display(s) from sleeping when on AC power in GNOME during testing - pts-core: Clean-up more code used during the test execution process - pts-core: Rename SaveSystemDetails user-config.xml option to SaveSystemLogs - pts-core: Add option to archive a test's installation log to a sub-directory of the results file - pts-core: Check for user-config-template.xml template in pts-core/static/ - pts-core: Add PTS Desktop Live user-config.xml template - pts-core: Move txt file lists from pts-core/static/ to pts-core/static/lists/ - pts-core: Allow test options to be specified externally via PRESET_OPTIONS environmental variable (see commit for example) - pts-core: Fix bug where from GTK2 GUI selecting to not save test results would prompt you from CLI to save results or not - pts-core: Vastly re-work the pts-includes-run_options code - pts-core: Move images to pts-core/static/images/ - pts-core: Create modules tag section in user-config.xml, move default modules to load into the LoadModules tag instead of text file - pts-core: Start adding user-interface options to the user-config.xml - pts-core: Updates for library / Phoromatic server usage - pts-core: Don't ask user whether to try again on a failed test download when in automated/batch mode - pts-core: When installing external dependencies fails, continue installing just the tests where the dependencies are satisfied] - pts-core: Add __event_user_error hook to PTS module API - phoromatic: Prevent overloading the Phoromatic server if the client module keeps trying to communicate too many times per minute - phoromatic: Support for reporting system/PTS warnings to Phoromatic server - phoromatic: Support for setting the default system title on the Phoromatic server as the test system's hostname - phoromatic: Report new system software / hardware for test system to Phoromatic server when appropriate - phoromatic: Add support for uploading Phoromatic-sanctioned test results to Phoronix Global, if Phoromatic server tells it to - phoromatic: Add support for Phoromatic server to tell client whether or not to archive the test results locally upon completion - phodevi: Improve phodevi smart caching, bring actual caching into pts-core and place the cache_store in the core.pt2so - phodevi: Fix possible space when getting resolutions from xrandr - phodevi: Don't report GPU memory clock in GPU string when GPU memory clock is 0MHz (NVIDIA reports this for at least some IGPs) - pts: Add workstation test suite - pts: Add disk-ssd test suite - pts: Revamp server test suite - documentation: Add a basic reviewer's guide Phoronix Test Suite 2.2 Beta 1 October 27, 2009 - pts-core: Fix for running result files that have forced AA/AF levels and then fail to merge - pts-core: On missing timezone setting, set to UTC if the PHP version is 5.3.0 or newer, emits a warning otherwise - pts-core: Rename change-results-display-order option command to reorder-result-file - pts-core: Add edit-result-file meta option - pts-core: Add MinimumLength tag to XML test profile specification - pts-core: Add MaximumLength tag to XML test profile specification - pts-core: Few fixes/changes to test execution code - pts-core: When dealing with the stats support for validating test results, don't increase the run count prematurely - pts-core: Fend off divide by zero errors in the standard deviation code - pts-core: Improve performance of PTS assignment functions - pts-core: Don't remove the PTS run_lock when running a secondary instance of PTS - pts-core: Add debug-run option to provide more run-time information to assist test profile writers in debugging / verifying profiles - pts-core: Drop central pts-core debugging code since it was very rarely used and not too helpful - pts-core: Add in additional LC_NUMERIC override to eliminate non-US decimal problems with test results - pts-core: Various test run code clean-ups - pts-core: With make-download-cache option only check for downloads on installed tests - pts-core: Support "all" as an argument with remove-installed-test option - pts-core: Improve object security - pts-core: Improve desktop responsiveness of GTK2 GUI - pts-core: Add automated Internet connectivity check on start - pts-core: More efficient paths for determining reference system comparisons - pts-core: Add __pre_test_download, __interim_test_download, and __post_test_download hooks to the PTS module API - pts-core: Start work on GTK2 GUI interface for during the test installation and run processes - pts-core: Rewrite web-browser launching code - pts-core: Rework list-tests option code - pts-core: Build select caches on start-up when running GTK2 GUI - pts-core: New bash completion support - pts-core: Support using the update_checker module from the GTK2 GUI for notifying of new PTS releases - pts-core: Add initial bisect module to allow users to hook PTS into any Git repository for bisecting with external script - pts-core: Use pts_test_profile within pts-includes-run - pts-core: Check for allow_url_fopen php.ini setting if it's disabled rather than letting it produce a warning - pts-core: Rename the pts_standard_display_mode to pts_basic_display_mode - pts-core: When running in batch mode or with debug-run, at end of testing report any tests/options that failed to properly run - pts-core: When tests are not installed when called in run-test option, prompt the user to automatically install the tests from there - pts-core: At end of the install process, list all tests that failed to properly install - pts-core: Various bug fixes - phodevi: Fend off possible infinite loop on OpenBSD when phodevi_parser::read_sysctl() fails - phodevi: Fix for reporting fglrx version string with newer versions of ATI Catalyst Linux driver - phodevi: Improve motherboard detection on BSD operating systems - phodevi: Improve CPU temperature detection on BSD operating systems - tandem_Xml: XML parsing fix when reading - pts: Fix for prey test profile - pts: Update openal external dependency in fedora-packages.xml - pts: Update compress-7zip test profile against p7zip 9.04 version - pts: Update sqlite test profile against SQLite 3.6.19 - pts: Update wine-unstable base test profile against Wine 1.1.32 - pts: Update graphics-magick test profile against GraphicsMagick 1.3.7 - pts: Use fedora-packages.xml external dependencies on CentOS instead of centos-packages.xml that is the same but less maintained - pts: Upstream request regarding cmake change for minion test profile Phoronix Test Suite 2.2 Alpha 4 October 12, 2009 - pts-core: Fix regression that caused running/installing suites to fail from Alpha 3 - pts-core: Add support for stopping/skipping the current test by touching ~/.phoronix-test-suite/skip-test during the process - pts-core: Remember radio and check button selects in menu on GTK2 GUI for the duration of the program - pts-core: Optimize a few common code paths - pts-core: Improve detection of Catalyst driver with newer releases - pts-core: Don't go awry when computing standard deviation on an array that may also contain errors from a test run due to parsing failure - pts-core: Fix fatal error message with GtkWindow missing - pts-core: Fend off possible warnings on pts_test_option - pts-core: Rename pts_batch_display_mode to pts_concise_display_mode - pts-core: Fix in subtitle reporting on graphs for tests with no options under certain conditions where it reported ":" - pts-core: When using rename-identifier-in-result-file option, rename the benchmark-logs and system-logs folders too for that identifier - pts-core: When using remove-from-result-file, remove the benchmark-logs and system-logs folders for that identifier if present - pts-core: Move system parsing functions out of pts-core and into phodevi_parser object in Phodevi - pts-core: Support exporting some functions from pts-core to the parse-results process during test runs - phodevi: Don't try using aticonfig when reading the AMDPCSDB on an unsupported graphics adapter, use the internal parser instead - phodevi: Support reading OpenGL vendor string - tandem_Xml: Optimize the XML string parser - pts: Updates to hpcc test profile - pts: Add initial opencl-ati test profile - pts: Add python-boost-development, boost-thread-development, and python-numpy external dependencies - pts: Add initial pyopencl test profile - pts: Update Nexuiz test profile against Nexuiz 2.5.2 - pts: Update netbook test suite - pts: Change over relevant test profiles to using pts_report_numeric_result() rather than print statements Phoronix Test Suite 2.2 Alpha 3 September 28, 2009 - pts-core: Add support for HTTP communication through a proxy server - pts-core: Add network-setup option for configuring network settings - pts-core: Add NoNetworkCommunication boolean option to user-config.xml for disabling network access - pts-core: Set timeout on HTTP connections to eight seconds - pts-core: Fix for results not showing up if renaming the first result identifier using rename-identifier-in-result-file option - pts-core: Fixes for FreeBSD 8.0 support - pts-core: Fix for reporting "Already Installed" tests with install option - pts-core: Better handle toggle_screensaver module when xdg-screensaver is missing - pts-core: Greater fallback disk support, should help with some BSD operating systems - pts-core: Add support for pts-core to dynamically increase a test's run count if the standard deviation exceeds a predefined threshold - pts-core: Add DynamicRunCount and LimitDynamicToTestLength for controlling the statistics / standard deviation settings - pts-core: Add StandardDeviationThreshold to user-config.xml for setting the standard deviation threshold percentage - pts-core: Better support floating values within the preferences window of the GTK2 GUI - pts-core: Add batch-install option if only to run the install process in the batch mode - pts-core: Updates to PTS user module architecture - pts-core: Support for having SH modules in the module local directory - pts-core: Standardize PTS test comparison hashes - pts-core: If a test needs RequiresRoot access and is running in batch mode and is not root, do not try to run the test - pts-core: When generating new graphs for a result file, delete any old files first - pts-core: Add ExportResultsTo as a user-config.xml option for hooking in external scripts for statistics support - pts-core: Support setting the result proportion for a test profile from writing it to ~/pts-results-proportion during the testing process - phodevi: Improve hardware detection for OpenSolaris SPARC systems using DDU information - phodevi: Improve motherboard detection for Sun SPARC systems - phodevi: Start new reporting infrastructure - tandem_Xml: Add addXmlObjectFromReader() function for improved performance - tandem_Xml: Add saveXMLFile() function - pts: Fixes for compress-lzma and compress-pbzip2 test profiles with name change of compressfile - pts: Fix for warsow test profile results not showing up on Linux - pts: Support using aptitude for external dependencies when available on Ubuntu/Debian - pts: Update minion test profile against Minion 0.9 - pts: Add OpenMPI to external dependencies as openmpi-development - pts: Add ATLAS math to external dependencies as atlas-development - pts: Add hpcc test profile for HPC Challenge Phoronix Test Suite 2.2 Alpha 2 September 15, 2009 - pts-core: Add display mode support to download-test-files option - pts-core: Handle pts_storage_object on failure correctly to avoid fatal error during testing process - pts-core: Export $DEBUG_REAL_HOME environmental variable to all test scripts - pts-core: Fix reporting of test notes at end of testing process - pts-core: Release the run_lock when a test is running and returns due to an error - pts-core: With the batch display mode, report the "estimated time remaining" at the start of each run - pts-core: Add change-results-display-order option for changing the ordering of the results within the results viewer / graphs - pts-core: Add rename-identifier-in-result-file option for changing the name of a test identifier within a results file - pts-core: With GTK2 GUI don't get to the point of emiting a fatal error over GtkWindow - pts-core: No longer support having test result XML files outside of the test-results/ directory where an absolute path was supplied to PTS - pts-core: Add support for performing argument / start-up checks for a PTS option prior to ever calling the run function - pts-core: When a test installation fails, save the install.log to install-failed.log - pts-core: Add option in batch-setup for still prompting for test option selection when running in batch mode - phodevi: Don't repeat the system vendor in motherboard string if it's also present in the product string - phodevi: Don't report hard drive bytes on Mac OS X 10.6 when reading the capacity of a disk - pts: Update Fedora external dependencies XML for blas-development and popt - pts: Update OpenSolaris external dependencies XML - pts: Update warsow test profile against Warsow 0.5 - pts: Update gnupg test profile against GnuPG 2.0.11 - pts: Update build-imagemagick test profile against ImageMagick 6.5.5 - pts: Use OpenMP support in stream test profile - pts: Build libpng within graphics-magick test profile so it will run on Mac OS X 10.6 - pts: Add aio-stress test profile Phoronix Test Suite 2.2 Alpha 1 August 27, 2009 - pts-core: Begin writing the results XML during the test run process earlier - pts-core: When a test is running, save the active pts_test_run_manager to a pts_storage_object on the disk - pts-core: Backup the XML results when a test is running to active.xml in the result's folder - pts-core: Add recover-run option for recovering the test results / finish running the tests when a crash had occured - pts-core: Fix bug with the result identifier being empty when using list-saved-results / list-results - pts-core: Setup a pt2so object for storing some pts-core data using a pts_storage_object, move some of these items out of user-config.xml - pts-core: Move out the modules that are loaded by a default to a separate file - pts-core: Add support for writing to different display modes / abstract out the output process from the testing process - pts-core: Drop the email_results module since using Phoromatic is a better solution - pts-core: Add a display mode for batch runs or when DefaultDisplayMode in the user-config.xml is set to "BATCH" - pts-core: Add support to allow anonymous usage reporting / statistics information - pts-core: Add "free" virtual suite that contains all tests that are of a FREE type for its license - pts-core: Multiple download cache directories can be specified in the user-config.xml and PTS_DOWNLOAD_CACHE environmental variable when delimited by colon - pts-core: Move relevant functions that touch hardware settings / properties out of pts-core and now using the phodevi::set_property() framework - pts-core: Fix check buttons for boolean values in the GTK2 GUI preferences window - pts-core: Allow the display mode to be set using PTS_DISPLAY_MODE environmental variable - pts-core: Add display mode support when a test is being installed - pts-core: Add ArchitectureSpecific tag support to distro-xml files for specifying packages to install on only select architectures for the OS - pts-core: Rework test timers to avoid false results on crashes - pts-core: Improve estimated run time reporting when running tests - pts-core: Handle the results identifer and saved results file name within the pts_test_run_manager - pts-core: Add experimental support for weighted suites / results - pts-core: Add "cache share" support for test profiles and the AllowCacheShare XML tag to expose this functionality - pts-core: Add "Test All Options" to test menu when prompting for test option selection - pts-core: Don't uselessly prompt a user for test options when trying to run an unsupported test - pts-core: Allow the user to select multiple test options when running a test by delimiting each option with a comma - pts-core: When using analyze-batch, support using bar graphs on comparisons where relevant, instead of just line graphs - pts-core: Don't repeat reporting the system hardware/software for the same results identifier in a results file - pts-core: Smarter detection when dealing with user trying to input a results identifier that is already found in the results file - pts-core: Launch web browser (instead of DashCode) on Mac OS X for analyze-batch and merge-results command - pts-core: Add remove-from-result-file option for removing a set of test results from a saved file - pts-core: Don't report the elapsed time for a test run when it's using a cache share or no valid results were gathered - pts-core: Stop forcing the time-zone to UTC - phodevi: Be more non-RandR friendly in phodevi_gpu::gpu_available_modes() - phodevi: Add infrastructure so that properties / settings can be set using phodevi::set_property() - phodevi: Add CPU usage monitoring support for Mac OS X - phodevi: Improve memory capacity detection on newer Apple systems - phodevi: Don't repeat the memory reporting in GPU string on Mac OS X - phodevi: Add sensor for reading system's uptime through system object - tandem_XmlWriter: Don't add the "Generated" timestamp each time that getXML() is called, since it's now being hit multiple times with each test run - pts_Graph: Properly order keys in the header when rendering - pts: Add glibc-development as an external dependency for providing GNU C library development files - pts: Add python external dependency for Python language - pts: Add stream test profile for Stream memory benchmark - pts: Add tachyon test profile for Tachyon Parallel Ray-Tracing benchmark - pts: Add python-environment base test profile for placing external dependency on python and reporting Python version to test notes - pts: Add pybench test profile for Python's PyBench - pts: Add tscp test profile for the chess benchmark - pts: Add chess test suite for test profiles that use chess AI - pts: Add john-the-ripper test profile for John The Ripper password cracker benchmark - pts: Add geekbench test profile for Primate Labs Geekbench benchmark - pts: Add npb test profile for NASA NAS Parallel Benchmark - pts: Drop test length option from ramspeed test profile, default to 10 - pts: Add Mac OS X support for openarena test profile - pts: Add Mac OS X support to warsow test profile - pts: In nexuiz test profile change from demos/bench1 to demos/demo2 for now - pts: In video-cpu-usage test profile add support to use CoreVideo vo adapter on Mac OS X - pts: Update graphics-magick test profile against GraphicsMagick 1.3.6 Phoronix Test Suite 2.0.0 "Sandtorg" August 4, 2009 - pts-core: Don't prompt for download mirror selection if the option is enabled, but running from the GUI - pts-core: Don't report "Comparison" multiple times when using the reference-comparison option - phodevi: Add LXDE desktop environment detection - pts: Add two more reference comparison systems - pts: minion test profile updates - pts: Update workstation-graphics test suite Phoronix Test Suite 2.0.0 Beta 4 July 28, 2009 - pts-core: For the "all" virtual suite, don't include tests that have a ResultFormat of NO_RESULT, PASS_FAIL, or MULTI_PASS_FAIL - pts-core: Clean-up pts_test_file_download object - pts-core: For GTK2 GUI change around event reporting for test installation - pts-core: Don't require trailing slash for user-config.xml paths - pts-core: Properly handle test profiles with no files to be downloaded in pts_test_download_files_locally_available() - pts-core: When using run-test in a batch mode and automated mode, but batch-setup hasn't been run, don't output an error - pts-core: Few fixes for Phoronix Global comparisons from GTK2 GUI interface - pts-core: Don't list test results when they are just the reference system comparison IDs from Phoronix Global - phodevi: Fix regression that caused system and CPU temperatures to not be reported through LM_Sensors interface - phodevi: Don't report disk size on hard disk identifier string when size equals 1GB, since that would be due to incorrect size - pts: Fix prey test profile bug in key location detection for key test profile by using $DEBUG_REAL_HOME in test install script - pts: Update boost packages for ubuntu-packages.xml external dependencies - pts: For vdrift test profile, don't grab the mouse - pts: Add glut as an external dependency to supertuxkart test profile - pts: Update compress-pbzip2 test profile to use 256MB compression file - documentation: Add Frequently Asked Questions - documentation: Add PTS Desktop Live - documentation: Few small updates Phoronix Test Suite 2.0.0 Beta 3 July 21, 2009 - pts-core: Small bug fixes and code clean-ups throughout - pts-core: Add new functionality to reference system comparison function - pts-core: Fixes for Phoronix Global log-in from GTK2 GUI - pts-core: More efficient pts_result_file object - pts-core: Don't let the same reference system result be merged into a test result when it was already merged - pts-core: Allow unique test run identifiers to be repeated if the new test run contains no repeated tests from result file - pts-core: Fix bug where tests that use Cascading Test Profiles would not have their extensions installed in a virtual suite - phodevi: Don't try calling glxinfo when it's not available - phodevi: Don't report PCI revision for graphics card model string - phodevi: Fixes for DragonFly BSD support - phodevi: Add support for reading motherboard information from new ACPI oid with sysctl on *BSD - phodevi: Add basic file-system detection support on *BSD - pts: Update unigine-sanctuary test profile to Unigine Sanctuary 2.2 - pts: Update unigine-tropics test profile to Unigine Tropics 1.2 - pts: Update download locations in etqw-demo test profile - pts: Update vdrift test profile against vDrift 2009-06-15 - pts: Update OpenSuSE External Dependencies - pts: Add External Dependencies support for DragonflyBSD through the NetBSD pkgsrc support - pts: Update Mandriva Linux External Dependencies - pts: Add supertuxkart test profile for SuperTuxKart racing game Phoronix Test Suite 2.0.0 Beta 2 July 7, 2009 - pts-core: Only show Installed Suites tab in GTK2 GUI when there is at least one suite installed - pts-core: Fix for undefined variable with test description when calling 2+ suites to run in batch mode - pts-core: Add notify_send_events module for reporting test installation/run statuses to notification daemon - pts-core: Add GSID for Phoronix Global usage - pts-core: Allow suites to override test options / XML values for a test profile from within a suite by using the OverrideTestOptions tag - pts-core: Add TOTAL_LOOP_TIME environmental variable for having pts-core run a loop of the specified test(s) until certain time is reached - pts-core: Add TOTAL_LOOP_COUNT environmental variable for having pts-core run a loop of the specified test(s) a specified number of times - pts-core: Add user-config-set option for allowing user configuration values to be set through PTS instead of modifying XML - pts-core: Add user-config-get option for reading user configuration option values - pts-core: Rename initial-config user option to user-config-reset - pts-core: Build result-info option capabilities into generic info command - pts-core: Small bug fixes and code clean-ups throughout - phodevi: Add NILFS2 file-system detection support - pts: Add tcl to PTS External Dependencies - pts: Small OpenSolaris updates - pts: Add perl as an external dependency to build-imagemagick - pts: Fix lightsmark test profile when running in the test suites - pts: Update PostgreSQL to version 8.4.0 in pgbench test profile - pts: Update wine-unstable base test profile to WINE 1.1.25 Phoronix Test Suite 2.0.0 Beta 1 June 14, 2009 - pts-core: Fix system monitoring reporting of values in test results - pts-core: Proper handling of line graphs in test results - pts-core: Make all test extensions available through environmental variables, helpful when a test extends a test - pts-core: Rewrite analyze-batch option entirely and use new pts_result_file_analyze manager engine and other new features - pts-core: Support setting up the XSL results viewer when running the refresh-graphs command - pts-core: Disable PCQS suite downloader - pts-core: With GTK2 GUI, only show "Installed Tests" tab when there are tests installed - pts-core: Support checking /var/cache/phoronix-test-suite/ as a possible PTS download-cache directory - pts-core: Fix test options not showing up when selecting a single test to run from the GTK2 GUI - pts-core: Support different default user-config.xml options when running the PTS live OS - pts-core: Support different defaults in GTK2 GUI when running the PTS live OS - pts-core: When selecting multiple tests/suites from GTK2 GUI, support both installing and running tests from the benchmark button click - pts-core: Set tries to 3 when using wget downloader - pts-core: Don't overflow the test options window when there are many tests/options to be displayed - pts-core: Add a colored header bar along the top of the GTK2 GUI for indicating important buttons/events rather than using the main frame - pts-core: Fix in reference-comparison support for handling reference systems that have multiple result sets - phodevi: Add a few more video modes to phodevi_gpu to ignore - pts: Update mpich2 in mrbayes test profile - pts: Add mplayer-base base test profile for providing installation of new mplayer/mencoder build with XvMC/VDPAU/etc - pts: Switch video-extensions test profile to using mplayer-base and support testing VDPAU - pts: Add video-cpu-usage test profile to monitor CPU usage during video playback with different video outputs - pts: Switch mencoder test profile to using mplayer-base for its mplayer/mencoder build - pts: Add desktop-graphics suite - pts: Add cpu suite - pts: Add workstation-graphics suite - pts: Add server-motherboard suite - pts: Update linux-system, netbook test suites - pts: Support PTS External Dependencies on the PTS Linux OS - pts: Compiler fix for nero2d test profile - pts: Update PTS External Dependencies support for Fedora x86_64 Phoronix Test Suite 2.0.0 Alpha 3 June 1, 2009 - pts-core: Add result-file-to-text option for outputting result file/results to the terminal - pts-core: Add result-file-to-csv option for outputting result file/results to CSV - pts-core: Add external dependencies window to GTK2 GUI for showing installed/missing test dependencies - pts-core: Various code cleaning and function enhancements - pts-core: Only initialize the system tray icon for GTK2 GUI when GtkStatusIcon is available - pts-core: Add pts_test_notes_manager - pts-core: Add support for test run scripts to write a test-exit-status where if it's set to a value not 0 it means test run failed - pts-core: Fix regression in pts_format_time_string() in Alpha 2 that caused the minutes to be calculated wrong - pts-core: Add estimate-run-time option for providing a detailed estimate of how much time is needed to run a test/suite/result file - pts-core: Add install-time support for skipping test installations using SKIP_TESTS - pts-core: Few PHP warning fixes - pts-core: Updates for OpenSolaris support - pts-core: When a test install fails based upon install-exit-status, remove pts-install.xml - pts-core: Add bash auto-completion support for basic PTS commands - pts-core: Add $PTS_TEST_ARGUMENTS environmental variable during testing that contains a copy of the arguments set for that test run - pts-core: Output download URL when a download fails / MD5 checksum doesn't match - pts-core: Add validate-test-profile option to catch common errors/warnings when writing a test profile - pts-core: Add validate-test-suite option to catch common errors/warnings when writing a test suite - pts-core: Add menu item to GTK2 GUI for showing tests where all needed test files are available locally or in download cache - pts-core: When a test installation fails based upon a non-zero exit status, wipe out the files it created during the install process - pts-core: Support showing suites with and without where all external dependencies are satisfied and where test files available locally - phodevi: Improve file-system detection, add detection for Btrfs instead of reporting 0x9123683e - phodevi: Add monitor name detection support when using NVIDIA graphics - phodevi: Move a few minor properties from phodevi_gpu to phodevi_monitor - phodevi: Add support for OpenSolaris 2009.06 - pts: Add kernel test suite - pts: Update jxrendermark test profile against JXRenderMark 1.0.1 - pts: Update OpenSolaris External Dependencies - pts: Add postmark test profile for NetApp's PostMark disk benchmark - pts: Add blogbench test profile for testing filesystem / disk performance similar to load produced by a web-blog server - pts: Add n-queens test profile for N-Queens OpenMP benchmark - pts: Add openmp test suite for containing tests that use OpenMP - pts: Update espeak test profile to eSpeak version 1.40.02 - pts: Update nearly all test profiles to take advantage of exit status feature in PTS 2.0 - pts: Trivial clean-ups in the scripts for a majority of the test profiles - pts: Finish replacing $THIS_DIR with $HOME in test profile installation scripts - pts: Conserve space in some test profiles by removing files that are not needed - pts: Add more download mirrors for files in many of the test profiles - pts: Update md-gromacs test profile to version 4.0.5 - pts: Update mafft test profile to version 6.706 - bilde_renderer: Support interfacing for Phoromatic server usage Phoronix Test Suite 2.0.0 Alpha 2 May 24, 2009 - pts-core: Fix for showing tests in the GTK2 GUI from Alpha 1 - pts-core: Various GTK2 GUI improvements - pts-core: Add 1.77 ratio to available modes in phodevi_gpu for supporting 1920 x 1080 resolution - pts-core: Various code clean-ups - pts-core: Add DefaultBrowser tag to user-config.xml to allow the user to override the web browser auto detection - pts-core: Add extract-from-result-file option for extracting a single test run from a merged results file - pts-core: Various bug fixes from Deanjo - pts-core: Cleanup and revise PTS installation External Dependency functions - pts-core: Add list-installed-dependencies option - pts-core: Add list-missing-dependencies option - pts-core: Add view option to GTK2 GUI for displaying available tests based upon external dependency criteria - pts-core: Add SKIP_TESTS environmental variable for specifying test identifier(s) (delimited by comma) to override and skip from testing - pts-core: Rewrite pts_generate_graphs() so that it can be supported for Phoronix Global / Phoromatic usage - pts-core: Add UsePhodeviCache option to user-config.xml for toggling whether to enable Phodevi smart cache for PTS - pts-core: Add support for test install scripts to write an install-exit-status where if it's set to a value not 0 it means install failed - phodevi: Support monitoring the system temperature from the ACPI TZ00 thermal zone - phodevi: Fix in Xfce 4 desktop version detection - phodevi: Report video memory detection for some GPUs, at least when using the xf86-video-ati driver - phodevi: Report video memory size for GPUs where the driver in use is Mesa - pts: Add dcraw test profile for RAW image decoding benchmark - pts: Add sudokut test profile for a Sudoku solver benchmark - pts: Add fftw3-development external dependency for Fast Fourier Transform 3 library - pts: Add blas-development external dependency for Basic Linear Algebra Subroutine library - pts: Add lapack-development external dependency for LAPACK - pts: Add cmake external dependency for cmake - pts: Add boost-development external dependency for Boost development libraries - pts: Add bzip2-development external dependency for BZIP2 development libraries - pts: Add nero2d test profile for Open FMM Nero2D TM/TE electromagnetic software solver - pts: Add minion test profile for Minion solver - pts: Support using multiple threads for FFmpeg test profile - pts: Update filesystem test suite - pts: Add External Dependencies support for Zenwalk Linux distribution - pts: Update disk test suite - pts: Drop system-disk test suite, since basically the same as the disk test suite - pts: Update linux-system test suite - toggle_screensaver: Support using gconftool-2 for toggling GNOME screensaver Phoronix Test Suite 2.0.0 Alpha 1 May 10, 2009 - pts-core: Support 1.70 mode ratio in hw_gpu_available_modes() which will allow auto-resolution to select 1024x600 on netbooks - pts-core: Initial support for being able to select multiple test/suite/result entries from the notebook menu area - pts-core: Fix bug where remove-all-results option would not actually remove the results - pts-core: Add EnvironmentTestingSize option for test profiles that require extra space on the HDD during testing process - pts-core: Begin work on Phodevi: Phoronix Device Interface - pts-core: With auto-* test options for disks, ensure the directory/point is writable - pts-core: Allow FORCE_TIMES_TO_RUN to be a lower value than what is defined - pts-core: Do not ask to display web browser when DISPLAY is not set - pts-core: When launching the GUI from a menu and it fails, show an error message in the web browser - pts-core: Move contents of pts-core/media/ into pts-core/static/ - pts-core: Add initial Phoromatic module - pts-core: Provide hard-coded paths when using PTS auto-* run options within a non-client environment - pts-core: Add OVERRIDE_VIDEO_MODES environmental variable for overriding video modes - pts-core: Add support for recursive sub-menus in the GTK2 GUI - pts-core: Reorganize menus in GTK2 GUI - pts-core: Add support for logging into Phoronix Global from GTK2 GUI - pts-core: Move sensor functions over to Phodevi framework using phodevi::read_sensor() - pts-core: Don't let pts_test_run_manager add another test request if the test with identical settings has already been added - pts-core: Don't enable defauts/check buttons on GTK2 GUI until something is selected - pts-core: Enable system tray icon for GTK2 GUI - pts-core: Report number of tests/suites/results in GTK2 notebook area above the select menu - pts-core: Fix bug that would drop raw results value when merging test results - pts-core: Provide smart caching for Phodevi to store software/hardware information that will not change between reboots - pts-core: Add list-installed-suites option - pts-core: Add list-unsupported-tests option - pts-core: Allow selecting multiple tests/suites to run at once from GTK2 GUI - pts-core: Fix GtkComboBox segmentation fault from GTK2 GUI - pts-core: Fix for NexentaCore operating system detection - pts-core: Set downloading timeout in pts_download() to 20 seconds - pts-core: Add finish-run option for completing remaining tests on an incomplete saved results file - pts-core: Fix file-locking system on tests where tests are not properly installed - pts: Update build-php test profile to use PHP 5.2.9 - pts: Set bork and compress-* test profiles to use the EnvironmentTestingSize tag - pts: Add Popt to PTS External Dependencies using popt generic name - pts: Add dbench test profile for the DBench disk benchmark - pts: Add dbench test profile to relevant suites - pts: Update sqlite test profile to SQLite 3.6.13 - pts: Add gmpbench test profile for GMP / GMPbench testing - pts: Add pgbench test profile for PostgreSQL testing - pts: Add tiobench test profile for Threaded I/O benchmark - pts: Add NUMA External Dependencies support using numa-development generic name - pts: Add crafty test profile for popular chess engine benchmark - pts: Add opstone-vsp test profile for Opstone Vector Scalar Product benchmark - pts: Add opstone-svsp test profile for Opstone Sparse-Vector Scalar Product benchmark - pts: Add opstone-svd test profile for Opstone Singular Value Decomposition benchmark - pts: Add opstone test suite of all opstone-* test profiles - pts: Add cachebench test profile - pts: Add apache test profile for Apache Benchmark - pts: Add server test suite of server tests - pts: Update build-mysql test profile download links - pts: Add curl to PTS External Dependencies for curl and curl library - pts: Specify SPECViewPerf version within Title for specviewperf9 and specviewperf10 to workaround bug - pts: Support more test profiles on Mac OS X, OpenSolaris, BSD - bilde_renderer: Drop integrated TTF font, switch to detecting installed system TTF fonts - pts_Graph: Tweak bar graph text settings - install-sh: Copy phoronix-test-suite.desktop to /usr/share/applications/ for the GUI ### For the change-log from older Phoronix Test Suite releases, visit: http://www.phoronix-test-suite.com/?k=release_history phoronix-test-suite/README0000644000175000017500000001202312223157104015471 0ustar michaelmichaelPhoronix Test Suite 4.8.3 The Phoronix Test Suite is the most comprehensive testing and benchmarking platform available for Linux, Solaris, Mac OS X, and BSD operating systems. The Phoronix Test Suite allows for carrying out tests in a fully automated manner from test installation to execution and reporting. All tests are meant to be easily reproducible, easy-to-use, and support fully automated execution. The Phoronix Test Suite is open-source under the GNU GPLv3 license and is developed by Phoronix Media in cooperation with partners. The Phoronix Test Suite itself is an open-source framework for conducting automated tests along with reporting of test results, detection of installed system software/hardware, and other features. Modules for the Phoronix Test Suite also allow for integration with git-bisect and other revision control systems for per-commit regression testing, system sensor monitoring, and other extras. This framework is designed to be an extensible architecture so that new test profiles and suites can be easily added to represent performance benchmarks, unit tests, and other quantitative and qualitative (e.g. image quality comparison) measurements. Available through OpenBenchmarking.org, a collaborative storage platform developed in conjunction with the Phoronix Test Suite, are more than 200 individual test profiles and more than 60 test suites available by default from the Phoronix Test Suite. Independent users are also able to upload their test results, profiles, and suites to OpenBenchmarking.org. A test profile is a single test that can be executed by the Phoronix Test Suite -- with a series of options possible within every test -- and a test suite is a seamless collection of test profiles and/or additional test suites. A test profile consists of a set of bash/shell scripts and XML files while a test suite is a single XML file. OpenBenchmarking.org also allows for conducting side-by-side result comparisons, a central location for storing and sharing test results, and collaborating over test data. Phoromatic is a complementary platform to OpenBenchmarking.org and the Phoronix Test Suite for interfacing with Phoronix Test Suite client(s) to automatically execute test runs on a timed, per-commit, or other trigger-driven basis. Phoromatic is designed for enterprise and allows for the easy management of multiple networked systems running Phoronix Test Suite clients via a single web-based interface. Professional support and custom engineering for the Phoronix Test Suite, Phoromatic, and OpenBenchmarking.org is available by contacting . Full details on the Phoronix Test Suite setup and usage is available from the included HTML/PDF documentation within the phoronix-test-suite package and from the Phoronix Test Suite web-site. INSTALLATION & SETUP: The Phoronix Test Suite is supported on Linux, *BSD, Solaris, Mac OS X, and Windows systems. However, the most full-featured and well supported operating system for conducting the tests is Linux with some non-basic functionality not being available under all platforms. The Phoronix Test Suite software/framework is compatible with all major CPU architectures (e.g. i686, x86_64, ARM, PowerPC), but not all of the test profiles/suites are compatible with all architectures. The Phoronix Test Suite can be installed for system-wide usage or run locally without installation from the extracted tar.gz/zip package. The only hard dependency on the Phoronix Test Suite is having command-line support for PHP (PHP 5.2+) installed. A complete PHP stack (e.g. with web-server) is NOT needed, but merely the PHP command-line support, which is widely available from operating system package managers under the name php, php5-cli, or php5. USAGE: The process to download, install/setup, execute, and report the results of a benchmark can be as simple as a command such as *phoronix-test-suite benchmark smallpt* to run a simple CPU test profile. If wishing to simply install a test, it's a matter of running *phoronix-test-suite install * and to run it's *phoronix-test-suite run *. There's also a batch mode for non-interactive benchmarking by first running *phoronix-test-suite batch-setup* and then using the *batch-run* sub-command rather than *run*. Viewing installed system hardware and software is available via *phoronix-test-suite system-info* or *phoronix-test-suite detailed-system-info* for greater verbosity. Facilitating a result comparison from OpenBenchmarking.org can be done by running, for example, *phoronix-test-suite benchmark 1204293-BY-PHORONIX357* if wishing to compare the results of the *http://openbenchmarking.org/result/1204293-BY-PHORONIX357* result file. Additional information is available from the Phoronix Test Suite web-site and the material bundled within the phoronix-test-suite/documentation/ directory. A man page is also bundled with the phoronix-test-suite software. phoronix-test-suite/COPYING0000644000175000017500000010451311014651667015664 0ustar michaelmichael GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . phoronix-test-suite/AUTHORS0000644000175000017500000000053112160637026015670 0ustar michaelmichaelCopyright 2008 - 2013 by Phoronix Media. Lead Architects: - Michael Larabel - Matthew Tippett There's also other individuals and organizations who have contributed patches, ideas, and made other contributions to the Phoronix Test Suite. These names are mentioned in the HTML / PDF documentation. phoronix-test-suite/pts-core/external-test-dependencies/xml/xsl/0000755000175000017500000000000012007007545025203 5ustar michaelmichaelphoronix-test-suite/pts-core/objects/phodevi/sensors/0000755000175000017500000000000012201104746023132 5ustar michaelmichaelphoronix-test-suite/pts-core/objects/phodevi/components/0000755000175000017500000000000012223041131023613 5ustar michaelmichaelphoronix-test-suite/pts-core/objects/phodevi/parsers/0000755000175000017500000000000012223040153023110 5ustar michaelmichaelphoronix-test-suite/pts-core/objects/client/display_modes/0000755000175000017500000000000012166053273024122 5ustar michaelmichaelphoronix-test-suite/pts-core/openbenchmarking.org/schemas/0000755000175000017500000000000012172340012024065 5ustar michaelmichaelphoronix-test-suite/pts-core/external-test-dependencies/xml/0000755000175000017500000000000012222574305024377 5ustar michaelmichaelphoronix-test-suite/pts-core/external-test-dependencies/scripts/0000755000175000017500000000000012130672161025263 5ustar michaelmichaelphoronix-test-suite/pts-core/static/certificates/0000755000175000017500000000000012007007544022305 5ustar michaelmichaelphoronix-test-suite/pts-core/static/xsl/0000755000175000017500000000000012172336630020452 5ustar michaelmichaelphoronix-test-suite/pts-core/static/scripts/0000755000175000017500000000000012202614615021327 5ustar michaelmichaelphoronix-test-suite/pts-core/static/examples/0000755000175000017500000000000012007007544021456 5ustar michaelmichaelphoronix-test-suite/pts-core/static/images/0000755000175000017500000000000012007007544021105 5ustar michaelmichaelphoronix-test-suite/pts-core/objects/pts_Graph/0000755000175000017500000000000012200177113021724 5ustar michaelmichaelphoronix-test-suite/pts-core/objects/nye_Xml/0000755000175000017500000000000012202504605021412 5ustar michaelmichaelphoronix-test-suite/pts-core/objects/phodevi/0000755000175000017500000000000012130605143021434 5ustar michaelmichaelphoronix-test-suite/pts-core/objects/bilde_renderer/0000755000175000017500000000000012007007544022747 5ustar michaelmichaelphoronix-test-suite/pts-core/objects/client/0000755000175000017500000000000012222311407021253 5ustar michaelmichaelphoronix-test-suite/pts-core/results-viewer/0000755000175000017500000000000012165661730021361 5ustar michaelmichaelphoronix-test-suite/pts-core/openbenchmarking.org/0000755000175000017500000000000012007007544022451 5ustar michaelmichaelphoronix-test-suite/pts-core/external-test-dependencies/0000755000175000017500000000000012007007544023574 5ustar michaelmichaelphoronix-test-suite/pts-core/static/0000755000175000017500000000000012007007544017640 5ustar michaelmichaelphoronix-test-suite/pts-core/modules/0000755000175000017500000000000012222545271020024 5ustar michaelmichaelphoronix-test-suite/pts-core/objects/0000755000175000017500000000000012222312152017773 5ustar michaelmichaelphoronix-test-suite/pts-core/commands/0000755000175000017500000000000012207413764020161 5ustar michaelmichaelphoronix-test-suite/documentation/man-pages/0000755000175000017500000000000012007007544021336 5ustar michaelmichaelphoronix-test-suite/documentation/includes/0000755000175000017500000000000012007007544021274 5ustar michaelmichaelphoronix-test-suite/documentation/old-docs/0000755000175000017500000000000012007007544021172 5ustar michaelmichaelphoronix-test-suite/documentation/stubs/0000755000175000017500000000000012212733060020623 5ustar michaelmichaelphoronix-test-suite/pts-core/0000755000175000017500000000000012223157055016354 5ustar michaelmichaelphoronix-test-suite/documentation/0000755000175000017500000000000012223157141017465 5ustar michaelmichaelphoronix-test-suite/0000755000175000017500000000000012223157156014622 5ustar michaelmichael