PageRenderTime 173ms CodeModel.GetById 58ms RepoModel.GetById 18ms app.codeStats 0ms

/pts-core/objects/client/pts_client.php

https://github.com/atlassianhlechner/phoronix-test-suite
PHP | 1839 lines | 1491 code | 236 blank | 112 comment | 373 complexity | fd0160af7de50f23ddf7906f8e2e517f MD5 | raw file
Possible License(s): GPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. Phoronix Test Suite
  4. URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
  5. Copyright (C) 2008 - 2014, Phoronix Media
  6. Copyright (C) 2008 - 2014, Michael Larabel
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 3 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. class pts_client
  19. {
  20. public static $display = false;
  21. private static $current_command = null;
  22. protected static $lock_pointers = null;
  23. private static $forked_pids = array();
  24. public static function create_lock($lock_file)
  25. {
  26. if(isset(self::$lock_pointers[$lock_file]) || is_writable(dirname($lock_file)) == false || disk_free_space(dirname($lock_file)) < 1024)
  27. {
  28. return false;
  29. }
  30. self::$lock_pointers[$lock_file] = fopen($lock_file, 'w');
  31. chmod($lock_file, 0644);
  32. return self::$lock_pointers[$lock_file] != false && flock(self::$lock_pointers[$lock_file], LOCK_EX | LOCK_NB);
  33. }
  34. public static function init()
  35. {
  36. set_time_limit(0);
  37. pts_define_directories(); // Define directories
  38. if(function_exists('cli_set_process_title'))
  39. {
  40. cli_set_process_title('Phoronix Test Suite');
  41. }
  42. if(defined('QUICK_START') && QUICK_START)
  43. {
  44. return true;
  45. }
  46. pts_define('PHP_BIN', pts_client::read_env('PHP_BIN'));
  47. pts_define('PTS_INIT_TIME', time());
  48. if(!defined('PHP_VERSION_ID'))
  49. {
  50. // PHP_VERSION_ID is only available in PHP 5.2.6 and later
  51. $php_version = explode('.', PHP_VERSION);
  52. pts_define('PHP_VERSION_ID', ($php_version[0] * 10000 + $php_version[1] * 100 + $php_version[2]));
  53. }
  54. $dir_init = array(PTS_USER_PATH);
  55. foreach($dir_init as $dir)
  56. {
  57. pts_file_io::mkdir($dir);
  58. }
  59. if(PTS_IS_CLIENT)
  60. {
  61. pts_network::client_startup();
  62. }
  63. self::core_storage_init_process();
  64. if(!is_file(PTS_TEMP_STORAGE))
  65. {
  66. self::build_temp_cache();
  67. }
  68. // XXX: technically the config init_files line shouldn't be needed since it should be dynamically called
  69. // pts_config::init_files();
  70. 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/')));
  71. 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/')));
  72. self::extended_init_process();
  73. $openbenchmarking = pts_storage_object::read_from_file(PTS_CORE_STORAGE, 'openbenchmarking');
  74. $openbenchmarking_account_settings = pts_storage_object::read_from_file(PTS_CORE_STORAGE, 'openbenchmarking_account_settings');
  75. if($openbenchmarking != null)
  76. {
  77. // OpenBenchmarking.org Account
  78. pts_openbenchmarking_client::init_account($openbenchmarking, $openbenchmarking_account_settings);
  79. }
  80. return true;
  81. }
  82. public static function module_framework_init()
  83. {
  84. // Process initially called when PTS starts up
  85. // Check for modules to auto-load from the configuration file
  86. $load_modules = pts_config::read_user_config('PhoronixTestSuite/Options/Modules/LoadModules', null);
  87. if(!empty($load_modules))
  88. {
  89. foreach(pts_strings::comma_explode($load_modules) as $module)
  90. {
  91. $module_r = pts_strings::trim_explode('=', $module);
  92. if(count($module_r) == 2)
  93. {
  94. // TODO: end up hooking this into pts_module::read_variable() rather than using the real env
  95. pts_client::set_environment_variable($module_r[0], $module_r[1]);
  96. }
  97. else
  98. {
  99. pts_module_manager::attach_module($module);
  100. }
  101. }
  102. }
  103. // Check for modules to load manually in PTS_MODULES
  104. if(($load_modules = pts_client::read_env('PTS_MODULES')) !== false)
  105. {
  106. foreach(pts_strings::comma_explode($load_modules) as $module)
  107. {
  108. if(!pts_module_manager::is_module_attached($module))
  109. {
  110. pts_module_manager::attach_module($module);
  111. }
  112. }
  113. }
  114. // Detect modules to load automatically
  115. pts_module_manager::detect_modules_to_load();
  116. // Clean-up modules list
  117. pts_module_manager::clean_module_list();
  118. // Reset counter
  119. pts_module_manager::set_current_module(null);
  120. // Load the modules
  121. $module_store_list = array();
  122. foreach(pts_module_manager::attached_modules() as $module)
  123. {
  124. $class_vars = get_class_vars($module);
  125. $module_store_vars = isset($class_vars['module_store_vars']) ? $class_vars['module_store_vars'] : null;
  126. if(is_array($module_store_vars))
  127. {
  128. foreach($module_store_vars as $store_var)
  129. {
  130. if(!in_array($store_var, $module_store_list))
  131. {
  132. array_push($module_store_list, $store_var);
  133. }
  134. }
  135. }
  136. }
  137. // Should any of the module options be saved to the results?
  138. foreach($module_store_list as $var)
  139. {
  140. $var_value = pts_client::read_env($var);
  141. if(!empty($var_value))
  142. {
  143. pts_module_manager::var_store_add($var, $var_value);
  144. }
  145. }
  146. pts_module_manager::module_process('__startup');
  147. pts_define('PTS_STARTUP_TASK_PERFORMED', true);
  148. register_shutdown_function(array('pts_module_manager', 'module_process'), '__shutdown');
  149. }
  150. public static function environmental_variables()
  151. {
  152. // The PTS environmental variables passed during the testing process, etc
  153. static $env_variables = null;
  154. if($env_variables == null)
  155. {
  156. $env_variables = array(
  157. 'PTS_VERSION' => PTS_VERSION,
  158. 'PTS_CODENAME' => PTS_CODENAME,
  159. 'PTS_DIR' => PTS_PATH,
  160. 'PHP_BIN' => PHP_BIN,
  161. 'NUM_CPU_CORES' => phodevi::read_property('cpu', 'core-count'),
  162. 'NUM_CPU_NODES' => phodevi::read_property('cpu', 'node-count'),
  163. 'NUM_CPU_JOBS' => (phodevi::read_property('cpu', 'core-count') * 2),
  164. 'SYS_MEMORY' => phodevi::read_property('memory', 'capacity'),
  165. 'VIDEO_MEMORY' => phodevi::read_property('gpu', 'memory-capacity'),
  166. 'VIDEO_WIDTH' => pts_arrays::first_element(phodevi::read_property('gpu', 'screen-resolution')),
  167. 'VIDEO_HEIGHT' => pts_arrays::last_element(phodevi::read_property('gpu', 'screen-resolution')),
  168. 'VIDEO_MONITOR_COUNT' => phodevi::read_property('monitor', 'count'),
  169. 'VIDEO_MONITOR_LAYOUT' => phodevi::read_property('monitor', 'layout'),
  170. 'VIDEO_MONITOR_SIZES' => phodevi::read_property('monitor', 'modes'),
  171. 'OPERATING_SYSTEM' => phodevi::read_property('system', 'vendor-identifier'),
  172. 'OS_VERSION' => phodevi::read_property('system', 'os-version'),
  173. 'OS_ARCH' => phodevi::read_property('system', 'kernel-architecture'),
  174. 'OS_TYPE' => phodevi::operating_system(),
  175. 'THIS_RUN_TIME' => PTS_INIT_TIME,
  176. 'DEBUG_REAL_HOME' => pts_client::user_home_directory()
  177. );
  178. if(!pts_client::executable_in_path('cc') && pts_client::executable_in_path('gcc'))
  179. {
  180. // This helps some test profiles build correctly if they don't do a cc check internally
  181. $env_variables['CC'] = 'gcc';
  182. }
  183. }
  184. return $env_variables;
  185. }
  186. public static function test_install_root_path()
  187. {
  188. if(getenv('PTS_TEST_INSTALL_ROOT_PATH') != false && is_dir(getenv('PTS_TEST_INSTALL_ROOT_PATH')) && is_writable(getenv('PTS_TEST_INSTALL_ROOT_PATH')))
  189. {
  190. return getenv('PTS_TEST_INSTALL_ROOT_PATH');
  191. }
  192. else
  193. {
  194. return PTS_TEST_INSTALL_DEFAULT_PATH;
  195. }
  196. }
  197. public static function user_run_save_variables()
  198. {
  199. static $runtime_variables = null;
  200. if($runtime_variables == null)
  201. {
  202. $runtime_variables = array(
  203. 'VIDEO_RESOLUTION' => phodevi::read_property('gpu', 'screen-resolution-string'),
  204. 'VIDEO_CARD' => phodevi::read_name('gpu'),
  205. 'VIDEO_DRIVER' => phodevi::read_property('system', 'display-driver-string'),
  206. 'OPENGL_DRIVER' => str_replace('(', '', phodevi::read_property('system', 'opengl-driver')),
  207. 'OPERATING_SYSTEM' => phodevi::read_property('system', 'operating-system'),
  208. 'PROCESSOR' => phodevi::read_name('cpu'),
  209. 'MOTHERBOARD' => phodevi::read_name('motherboard'),
  210. 'CHIPSET' => phodevi::read_name('chipset'),
  211. 'KERNEL_VERSION' => phodevi::read_property('system', 'kernel'),
  212. 'COMPILER' => phodevi::read_property('system', 'compiler'),
  213. 'HOSTNAME' => phodevi::read_property('system', 'hostname')
  214. );
  215. }
  216. return $runtime_variables;
  217. }
  218. public static function save_test_result($save_to = null, $save_results = null, $render_graphs = true, $result_identifier = null)
  219. {
  220. // Saves PTS result file
  221. if(substr($save_to, -4) != '.xml')
  222. {
  223. $save_to .= '.xml';
  224. }
  225. $save_to_dir = pts_client::setup_test_result_directory($save_to);
  226. if($save_to == null || $save_results == null)
  227. {
  228. $bool = false;
  229. }
  230. else
  231. {
  232. $save_name = basename($save_to, '.xml');
  233. if($save_name == 'composite' && $render_graphs)
  234. {
  235. pts_client::generate_result_file_graphs($save_results, $save_to_dir);
  236. }
  237. $bool = file_put_contents(PTS_SAVE_RESULTS_PATH . $save_to, $save_results);
  238. 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)))
  239. {
  240. // Save verbose system information here
  241. $system_log_dir = $save_to_dir . '/system-logs/' . $result_identifier . '/';
  242. pts_file_io::mkdir($system_log_dir, 0777, true);
  243. // Backup system files
  244. // TODO: move out these files/commands to log out to respective Phodevi components so only what's relevant will be logged
  245. $system_log_files = array(
  246. '/var/log/Xorg.0.log',
  247. '/proc/cpuinfo',
  248. '/proc/meminfo',
  249. '/proc/modules',
  250. '/proc/mounts',
  251. '/proc/cmdline',
  252. '/proc/version',
  253. '/etc/X11/xorg.conf',
  254. '/sys/kernel/debug/dri/0/radeon_pm_info',
  255. '/sys/kernel/debug/dri/0/i915_capabilities',
  256. '/sys/kernel/debug/dri/0/i915_cur_delayinfo',
  257. '/sys/kernel/debug/dri/0/i915_drpc_info',
  258. '/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies',
  259. );
  260. /*
  261. if(phodevi::is_linux())
  262. {
  263. // the kernel config file might just be too large to upload for now
  264. array_push($system_log_files, '/boot/config-' . php_uname('r'));
  265. }
  266. */
  267. foreach($system_log_files as $file)
  268. {
  269. if(is_file($file) && is_readable($file))
  270. {
  271. // copy() can't be used in this case since it will result in a blank file for /proc/ file-system
  272. $file_contents = file_get_contents($file);
  273. $file_contents = pts_strings::remove_line_timestamps($file_contents);
  274. file_put_contents($system_log_dir . basename($file), $file_contents);
  275. }
  276. }
  277. // Generate logs from system commands to backup
  278. $system_log_commands = array(
  279. 'lspci -mmkvvvnn',
  280. 'lscpu',
  281. 'cc -v',
  282. 'lsusb',
  283. 'lsmod',
  284. 'sensors',
  285. 'dmesg',
  286. 'vdpauinfo',
  287. 'cpufreq-info',
  288. 'glxinfo',
  289. 'clinfo',
  290. 'uname -a',
  291. // 'udisks --dump',
  292. 'upower --dump',
  293. );
  294. if(phodevi::is_bsd())
  295. {
  296. array_push($system_log_commands, 'sysctl -a');
  297. array_push($system_log_commands, 'kenv');
  298. }
  299. if(is_readable('/dev/mem'))
  300. {
  301. array_push($system_log_commands, 'dmidecode');
  302. }
  303. foreach($system_log_commands as $command_string)
  304. {
  305. $command = explode(' ', $command_string);
  306. if(($command_bin = pts_client::executable_in_path($command[0])))
  307. {
  308. $cmd_output = shell_exec('cd ' . dirname($command_bin) . ' && ./' . $command_string . ' 2>&1');
  309. // Try to filter out any serial numbers, etc.
  310. phodevi_vfs::cleanse_file($cmd_output, $command[0]);
  311. $cmd_output = pts_strings::remove_line_timestamps($cmd_output);
  312. file_put_contents($system_log_dir . $command[0], $cmd_output);
  313. }
  314. }
  315. // Dump some common / important environmental variables
  316. $environment_variables = array(
  317. 'PATH' => null,
  318. 'CFLAGS' => null,
  319. 'CXXFLAGS' => null,
  320. 'LD_LIBRARY_PATH' => null,
  321. 'CC' => null,
  322. 'CXX' => null,
  323. 'LIBGL_DRIVERS_PATH' => null
  324. );
  325. foreach($environment_variables as $variable => &$value)
  326. {
  327. $v = getenv($variable);
  328. if($v != null)
  329. {
  330. $value = $v;
  331. }
  332. else
  333. {
  334. unset($environment_variables[$variable]);
  335. }
  336. }
  337. if(!empty($environment_variables))
  338. {
  339. $variable_dump = null;
  340. foreach($environment_variables as $variable => $value)
  341. {
  342. $variable_dump .= $variable . '=' . $value . PHP_EOL;
  343. }
  344. file_put_contents($system_log_dir . 'environment-variables', $variable_dump);
  345. }
  346. }
  347. }
  348. return $bool;
  349. }
  350. public static function save_result_file(&$result_file_writer, $save_name)
  351. {
  352. // Save the test file
  353. // TODO: clean this up with pts_client::save_test_result
  354. $j = 1;
  355. while(is_file(PTS_SAVE_RESULTS_PATH . $save_name . '/test-' . $j . '.xml'))
  356. {
  357. $j++;
  358. }
  359. $real_name = $save_name . '/test-' . $j . '.xml';
  360. pts_client::save_test_result($real_name, $result_file_writer->get_xml());
  361. if(!is_file(PTS_SAVE_RESULTS_PATH . $save_name . '/composite.xml'))
  362. {
  363. 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());
  364. }
  365. else
  366. {
  367. // Merge Results
  368. $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));
  369. pts_client::save_test_result($save_name . '/composite.xml', $merged_results, true, $result_file_writer->get_result_identifier());
  370. }
  371. return $real_name;
  372. }
  373. public static function init_display_mode($flags = 0)
  374. {
  375. if(PTS_IS_WEB_CLIENT && !defined('PHOROMATIC_SERVER'))
  376. {
  377. self::$display = new pts_web_display_mode();
  378. return;
  379. }
  380. $env_mode = ($flags & pts_c::debug_mode) ? 'BASIC' : false;
  381. 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')))
  382. {
  383. case 'BASIC':
  384. self::$display = new pts_basic_display_mode();
  385. break;
  386. case 'BATCH':
  387. case 'CONCISE':
  388. self::$display = new pts_concise_display_mode();
  389. break;
  390. case 'DEFAULT':
  391. default:
  392. self::$display = new pts_concise_display_mode();
  393. break;
  394. }
  395. }
  396. private static function extended_init_process()
  397. {
  398. // Extended Initalization Process
  399. $directory_check = array(
  400. PTS_TEST_INSTALL_DEFAULT_PATH,
  401. PTS_SAVE_RESULTS_PATH,
  402. PTS_MODULE_LOCAL_PATH,
  403. PTS_MODULE_DATA_PATH,
  404. PTS_DOWNLOAD_CACHE_PATH,
  405. PTS_OPENBENCHMARKING_SCRATCH_PATH,
  406. PTS_TEST_PROFILE_PATH,
  407. PTS_TEST_SUITE_PATH,
  408. PTS_TEST_PROFILE_PATH . 'local/',
  409. PTS_TEST_SUITE_PATH . 'local/'
  410. );
  411. foreach($directory_check as $dir)
  412. {
  413. pts_file_io::mkdir($dir);
  414. }
  415. // Setup PTS Results Viewer
  416. pts_file_io::mkdir(PTS_SAVE_RESULTS_PATH . 'pts-results-viewer');
  417. foreach(pts_file_io::glob(PTS_RESULTS_VIEWER_PATH . '*') as $result_viewer_file)
  418. {
  419. copy($result_viewer_file, PTS_SAVE_RESULTS_PATH . 'pts-results-viewer/' . basename($result_viewer_file));
  420. }
  421. copy(PTS_CORE_STATIC_PATH . 'images/pts-106x55.png', PTS_SAVE_RESULTS_PATH . 'pts-results-viewer/pts-106x55.png');
  422. // Setup ~/.phoronix-test-suite/xsl/
  423. pts_file_io::mkdir(PTS_USER_PATH . 'xsl/');
  424. copy(PTS_CORE_STATIC_PATH . 'xsl/pts-test-installation-viewer.xsl', PTS_USER_PATH . 'xsl/' . 'pts-test-installation-viewer.xsl');
  425. copy(PTS_CORE_STATIC_PATH . 'xsl/pts-user-config-viewer.xsl', PTS_USER_PATH . 'xsl/' . 'pts-user-config-viewer.xsl');
  426. copy(PTS_CORE_STATIC_PATH . 'images/pts-308x160.png', PTS_USER_PATH . 'xsl/' . 'pts-logo.png');
  427. // pts_compatibility ops here
  428. pts_client::init_display_mode();
  429. }
  430. public static function program_requirement_checks($only_show_required = false)
  431. {
  432. $extension_checks = pts_needed_extensions();
  433. $printed_required_header = false;
  434. $printed_optional_header = false;
  435. foreach($extension_checks as $extension)
  436. {
  437. if($extension[1] == false)
  438. {
  439. if($extension[0] == 1)
  440. {
  441. // Oops, this extension is required
  442. if($printed_required_header == false)
  443. {
  444. echo PHP_EOL . 'The following PHP extensions are REQUIRED by the Phoronix Test Suite:' . PHP_EOL . PHP_EOL;
  445. $printed_required_header = true;
  446. }
  447. }
  448. else
  449. {
  450. if($only_show_required && $printed_required_header == false)
  451. {
  452. continue;
  453. }
  454. // This extension is missing but optional
  455. if($printed_optional_header == false)
  456. {
  457. echo PHP_EOL . ($printed_required_header ? null : 'NOTICE: ') . 'The following PHP extensions are OPTIONAL but recommended:' . PHP_EOL . PHP_EOL;
  458. $printed_optional_header = true;
  459. }
  460. }
  461. echo sprintf('%-8ls %-30ls' . PHP_EOL, $extension[2], $extension[3]);
  462. }
  463. }
  464. if($printed_required_header || $printed_optional_header)
  465. {
  466. echo PHP_EOL;
  467. if($printed_required_header)
  468. {
  469. exit;
  470. }
  471. }
  472. }
  473. private static function build_temp_cache()
  474. {
  475. $pso = pts_storage_object::recover_from_file(PTS_TEMP_STORAGE);
  476. if($pso == false)
  477. {
  478. $pso = new pts_storage_object();
  479. }
  480. $pso->add_object('environmental_variables_for_modules', pts_module_manager::modules_environmental_variables());
  481. $pso->add_object('command_alias_list', pts_documentation::client_commands_aliases());
  482. $pso->save_to_file(PTS_TEMP_STORAGE);
  483. }
  484. private static function core_storage_init_process()
  485. {
  486. $pso = pts_storage_object::recover_from_file(PTS_CORE_STORAGE);
  487. if($pso == false)
  488. {
  489. $pso = new pts_storage_object(true, true);
  490. }
  491. // OpenBenchmarking.org - GSID
  492. $global_gsid = $pso->read_object('global_system_id');
  493. $global_gsid_e = $pso->read_object('global_system_id_e');
  494. $global_gsid_p = $pso->read_object('global_system_id_p');
  495. if(empty($global_gsid) || pts_openbenchmarking::is_valid_gsid_format($global_gsid) == false)
  496. {
  497. // Global System ID for anonymous uploads, etc
  498. $requested_gsid = true;
  499. $global_gsid = pts_openbenchmarking_client::request_gsid();
  500. if(is_array($global_gsid))
  501. {
  502. $pso->add_object('global_system_id', $global_gsid['gsid']); // GSID
  503. $pso->add_object('global_system_id_p', $global_gsid['gsid_p']); // GSID_P
  504. $pso->add_object('global_system_id_e', $global_gsid['gsid_e']); // GSID_E
  505. pts_define('PTS_GSID', $global_gsid['gsid']);
  506. pts_define('PTS_GSID_E', $global_gsid['gsid_e']);
  507. }
  508. }
  509. else if(pts_openbenchmarking::is_valid_gsid_e_format($global_gsid_e) == false || pts_openbenchmarking::is_valid_gsid_p_format($global_gsid_p) == false)
  510. {
  511. pts_define('PTS_GSID', $global_gsid);
  512. $requested_gsid = false;
  513. $global_gsid = pts_openbenchmarking_client::retrieve_gsid();
  514. if(is_array($global_gsid))
  515. {
  516. $pso->add_object('global_system_id_p', $global_gsid['gsid_p']); // GSID_P
  517. $pso->add_object('global_system_id_e', $global_gsid['gsid_e']); // GSID_E
  518. pts_define('PTS_GSID_E', $global_gsid['gsid_e']);
  519. }
  520. }
  521. else
  522. {
  523. pts_define('PTS_GSID', $global_gsid);
  524. pts_define('PTS_GSID_E', $global_gsid_e);
  525. $requested_gsid = false;
  526. }
  527. // Last Run Processing
  528. $last_core_version = $pso->read_object('last_core_version');
  529. pts_define('FIRST_RUN_ON_PTS_UPGRADE', ($last_core_version != PTS_CORE_VERSION));
  530. if(FIRST_RUN_ON_PTS_UPGRADE || ($pso->read_object('last_php_version') != PTS_PHP_VERSION))
  531. {
  532. // Report any missing/recommended extensions
  533. self::program_requirement_checks();
  534. }
  535. if(FIRST_RUN_ON_PTS_UPGRADE)
  536. {
  537. if($requested_gsid == false)
  538. {
  539. pts_openbenchmarking_client::update_gsid();
  540. }
  541. pts_client::build_temp_cache();
  542. }
  543. $pso->add_object('last_core_version', PTS_CORE_VERSION); // PTS version last run
  544. $pso->add_object('last_php_version', PTS_PHP_VERSION); // PHP version last run
  545. //$last_pts_version = $pso->read_object('last_pts_version');
  546. // do something here with $last_pts_version if you want that information
  547. $pso->add_object('last_pts_version', PTS_VERSION); // PTS version last run
  548. // Last Run Processing
  549. $last_run = $pso->read_object('last_run_time');
  550. pts_define('IS_FIRST_RUN_TODAY', (substr($last_run, 0, 10) != date('Y-m-d')));
  551. $pso->add_object('last_run_time', date('Y-m-d H:i:s')); // Time PTS was last run
  552. // User Agreement Checking
  553. $agreement_cs = $pso->read_object('user_agreement_cs');
  554. $pso->add_object('user_agreement_cs', $agreement_cs); // User agreement check-sum
  555. // Phodevi Cache Handling
  556. $phodevi_cache = $pso->read_object('phodevi_smart_cache');
  557. if($phodevi_cache instanceof phodevi_cache && pts_flags::no_phodevi_cache() == false)
  558. {
  559. $phodevi_cache = $phodevi_cache->restore_cache(PTS_USER_PATH, PTS_CORE_VERSION);
  560. phodevi::set_device_cache($phodevi_cache);
  561. if(($external_phodevi_cache = pts_client::read_env('EXTERNAL_PHODEVI_CACHE')))
  562. {
  563. if(is_dir($external_phodevi_cache) && is_file($external_phodevi_cache . '/core.pt2so'))
  564. {
  565. $external_phodevi_cache .= '/core.pt2so';
  566. }
  567. if(is_file($external_phodevi_cache))
  568. {
  569. $external_phodevi_cache = pts_storage_object::force_recover_from_file($external_phodevi_cache);
  570. if($external_phodevi_cache != false)
  571. {
  572. $external_phodevi_cache = $external_phodevi_cache->read_object('phodevi_smart_cache');
  573. $external_phodevi_cache = $external_phodevi_cache->restore_cache(null, PTS_CORE_VERSION);
  574. if($external_phodevi_cache != false)
  575. {
  576. //unset($external_phodevi_cache['system']['operating-system']);
  577. //unset($external_phodevi_cache['system']['vendor-identifier']);
  578. phodevi::set_device_cache($external_phodevi_cache);
  579. }
  580. }
  581. }
  582. }
  583. }
  584. // Archive to disk
  585. $pso->save_to_file(PTS_CORE_STORAGE);
  586. }
  587. public static function user_agreement_check($command)
  588. {
  589. $pso = pts_storage_object::recover_from_file(PTS_CORE_STORAGE);
  590. if($pso == false)
  591. {
  592. return false;
  593. }
  594. $config_md5 = $pso->read_object('user_agreement_cs');
  595. $current_md5 = md5_file(PTS_PATH . 'pts-core/user-agreement.txt');
  596. if($config_md5 != $current_md5 || pts_config::read_user_config('PhoronixTestSuite/Options/OpenBenchmarking/AnonymousUsageReporting', 'UNKNOWN') == 'UNKNOWN')
  597. {
  598. $prompt_in_method = pts_client::check_command_for_function($command, 'pts_user_agreement_prompt');
  599. $user_agreement = file_get_contents(PTS_PATH . 'pts-core/user-agreement.txt');
  600. if($prompt_in_method)
  601. {
  602. $user_agreement_return = call_user_func(array($command, 'pts_user_agreement_prompt'), $user_agreement);
  603. if(is_array($user_agreement_return))
  604. {
  605. if(count($user_agreement_return) == 3)
  606. {
  607. list($agree, $usage_reporting, $hwsw_reporting) = $user_agreement_return;
  608. }
  609. else
  610. {
  611. $agree = array_shift($user_agreement_return);
  612. $usage_reporting = -1;
  613. $hwsw_reporting = -1;
  614. }
  615. }
  616. else
  617. {
  618. $agree = $user_agreement_return;
  619. $usage_reporting = -1;
  620. $hwsw_reporting = -1;
  621. }
  622. }
  623. if($prompt_in_method == false || $usage_reporting == -1 || $hwsw_reporting == -1)
  624. {
  625. pts_client::$display->generic_heading('User Agreement');
  626. echo wordwrap($user_agreement, 65);
  627. $agree = pts_flags::user_agreement_skip() || pts_user_io::prompt_bool_input('Do you agree to these terms and wish to proceed', true);
  628. if(pts_flags::no_openbenchmarking_reporting())
  629. {
  630. $usage_reporting = false;
  631. $hwsw_reporting = false;
  632. }
  633. else
  634. {
  635. $usage_reporting = $agree ? pts_user_io::prompt_bool_input('Enable anonymous usage / statistics reporting', true) : -1;
  636. $hwsw_reporting = $agree ? pts_user_io::prompt_bool_input('Enable anonymous statistical reporting of installed software / hardware', true) : -1;
  637. }
  638. }
  639. if($agree)
  640. {
  641. echo PHP_EOL;
  642. $pso->add_object('user_agreement_cs', $current_md5);
  643. $pso->save_to_file(PTS_CORE_STORAGE);
  644. }
  645. else
  646. {
  647. pts_client::exit_client('In order to run the Phoronix Test Suite, you must agree to the listed terms.');
  648. }
  649. pts_config::user_config_generate(array(
  650. 'PhoronixTestSuite/Options/OpenBenchmarking/AnonymousUsageReporting' => pts_config::bool_to_string($usage_reporting),
  651. 'PhoronixTestSuite/Options/OpenBenchmarking/AnonymousHardwareReporting' => pts_config::bool_to_string($hwsw_reporting),
  652. 'PhoronixTestSuite/Options/OpenBenchmarking/AnonymousSoftwareReporting' => pts_config::bool_to_string($hwsw_reporting)
  653. ));
  654. }
  655. }
  656. public static function swap_variables($user_str, $replace_call)
  657. {
  658. if(is_array($replace_call))
  659. {
  660. if(count($replace_call) != 2 || method_exists($replace_call[0], $replace_call[1]) == false)
  661. {
  662. echo PHP_EOL . 'Var Swap With Method Failed.' . PHP_EOL;
  663. return $user_str;
  664. }
  665. }
  666. else if(!function_exists($replace_call))
  667. {
  668. echo PHP_EOL . 'Var Swap With Function Failed.' . PHP_EOL;
  669. return $user_str;
  670. }
  671. $offset = 0;
  672. $replace_call_return = false;
  673. while($offset < strlen($user_str) && ($s = strpos($user_str, '$', $offset)) !== false)
  674. {
  675. $s++;
  676. $var_name = substr($user_str, $s, (($e = strpos($user_str, ' ', $s)) == false ? strlen($user_str) : $e) - $s);
  677. if($replace_call_return === false)
  678. {
  679. $replace_call_return = call_user_func($replace_call);
  680. }
  681. $var_replacement = isset($replace_call_return[$var_name]) ? $replace_call_return[$var_name] : null;
  682. if($var_replacement != null)
  683. {
  684. $user_str = str_replace('$' . $var_name, $var_replacement, $user_str);
  685. }
  686. else
  687. {
  688. // echo "\nVariable Swap For $var_name Failed.\n";
  689. }
  690. $offset = $s + strlen($var_replacement);
  691. }
  692. return $user_str;
  693. }
  694. public static function setup_test_result_directory($save_to)
  695. {
  696. $save_to_dir = PTS_SAVE_RESULTS_PATH . $save_to;
  697. if(strpos(basename($save_to_dir), '.'))
  698. {
  699. $save_to_dir = dirname($save_to_dir);
  700. }
  701. if($save_to_dir != '.')
  702. {
  703. pts_file_io::mkdir($save_to_dir);
  704. }
  705. file_put_contents($save_to_dir . '/index.html', '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html><head><title>Phoronix Test Suite</title><meta http-equiv="REFRESH" content="0;url=composite.xml"></HEAD><BODY></BODY></HTML>');
  706. return $save_to_dir;
  707. }
  708. public static function remove_installed_test(&$test_profile)
  709. {
  710. pts_file_io::delete($test_profile->get_install_dir(), null, true);
  711. }
  712. public static function exit_client($string = null, $exit_status = 0)
  713. {
  714. // Exit the Phoronix Test Suite client
  715. pts_define('PTS_EXIT', 1);
  716. if($string != null)
  717. {
  718. echo PHP_EOL . $string . PHP_EOL;
  719. }
  720. exit($exit_status);
  721. }
  722. public static function current_user()
  723. {
  724. // Current system user
  725. return ($pts_user = pts_openbenchmarking_client::user_name()) != null ? $pts_user : phodevi::read_property('system', 'username');
  726. }
  727. public static function user_home_directory()
  728. {
  729. // Gets the system user's home directory
  730. static $userhome = null;
  731. if($userhome == null)
  732. {
  733. if(function_exists('posix_getpwuid') && function_exists('posix_getuid'))
  734. {
  735. $userinfo = posix_getpwuid(posix_getuid());
  736. $userhome = $userinfo['dir'];
  737. }
  738. else if(($home = pts_client::read_env('HOME')))
  739. {
  740. $userhome = $home;
  741. }
  742. else if(($home = pts_client::read_env('HOMEPATH')))
  743. {
  744. $userhome = pts_client::read_env('HOMEDRIVE') . $home;
  745. }
  746. else
  747. {
  748. echo PHP_EOL . 'ERROR: Cannot find home directory.' . PHP_EOL;
  749. $userhome = null;
  750. }
  751. $userhome = pts_strings::add_trailing_slash($userhome);
  752. }
  753. return $userhome;
  754. }
  755. public static function test_profile_debug_message($message)
  756. {
  757. $reported = false;
  758. if((pts_c::$test_flags & pts_c::debug_mode))
  759. {
  760. pts_client::$display->test_run_instance_error($message);
  761. $reported = true;
  762. }
  763. return $reported;
  764. }
  765. public static function parse_home_directory($path)
  766. {
  767. // Find home directory if needed
  768. if(strpos($path, '~/') !== false)
  769. {
  770. $path = str_replace('~/', pts_client::user_home_directory(), $path);
  771. }
  772. return pts_strings::add_trailing_slash($path);
  773. }
  774. public static function xsl_results_viewer_graph_template()
  775. {
  776. $raw_xsl = file_get_contents(PTS_RESULTS_VIEWER_PATH . 'pts-results-viewer.xsl');
  777. // System Tables
  778. $conversions = array('systems', 'detailed_component', 'radar', 'overview', 'visualize');
  779. foreach($conversions as $convert)
  780. {
  781. $graph_string = pts_svg_dom::html_embed_code('result-graphs/' . $convert . '.BILDE_EXTENSION', 'SVG', array('width' => 'auto', 'height' => 'auto'), true);
  782. $raw_xsl = str_replace('<!-- ' . strtoupper($convert) . ' TAG -->', $graph_string, $raw_xsl);
  783. }
  784. // Result Graphs
  785. $graph_string = pts_svg_dom::html_embed_code('result-graphs/<xsl:number value="position()" />.BILDE_EXTENSION', 'SVG', array('width' => 'auto', 'height' => 'auto'), true);
  786. $raw_xsl = str_replace('<!-- GRAPH TAG -->', $graph_string, $raw_xsl);
  787. return $raw_xsl;
  788. }
  789. public static function generate_result_file_graphs($test_results_identifier, $save_to_dir = false)
  790. {
  791. if($save_to_dir)
  792. {
  793. if(pts_file_io::mkdir($save_to_dir . '/result-graphs') == false)
  794. {
  795. // Directory must exist, so remove any old graph files first
  796. foreach(pts_file_io::glob($save_to_dir . '/result-graphs/*') as $old_file)
  797. {
  798. unlink($old_file);
  799. }
  800. }
  801. }
  802. $result_file = new pts_result_file($test_results_identifier);
  803. $generated_graphs = array();
  804. $generated_graph_tables = false;
  805. // Render overview chart
  806. if($save_to_dir)
  807. {
  808. $chart = new pts_ResultFileTable($result_file);
  809. $chart->renderChart($save_to_dir . '/result-graphs/overview.BILDE_EXTENSION');
  810. $intent = -1;
  811. if(($intent = pts_result_file_analyzer::analyze_result_file_intent($result_file, $intent, true)) || $result_file->get_system_count() == 1)
  812. {
  813. $chart = new pts_ResultFileCompactSystemsTable($result_file, $intent);
  814. }
  815. else
  816. {
  817. $chart = new pts_ResultFileSystemsTable($result_file);
  818. }
  819. $chart->renderChart($save_to_dir . '/result-graphs/systems.BILDE_EXTENSION');
  820. unset($chart);
  821. if($intent && is_dir($save_to_dir . '/system-logs/'))
  822. {
  823. $chart = new pts_DetailedSystemComponentTable($result_file, $save_to_dir . '/system-logs/', $intent);
  824. if($chart)
  825. {
  826. $chart->renderChart($save_to_dir . '/result-graphs/detailed_component.BILDE_EXTENSION');
  827. }
  828. }
  829. }
  830. foreach($result_file->get_result_objects() as $key => $result_object)
  831. {
  832. $save_to = $save_to_dir;
  833. if($save_to_dir && is_dir($save_to_dir))
  834. {
  835. $save_to .= '/result-graphs/' . ($key + 1) . '.BILDE_EXTENSION';
  836. if(PTS_IS_CLIENT)
  837. {
  838. if($result_file->is_multi_way_comparison() || pts_client::read_env('GRAPH_GROUP_SIMILAR'))
  839. {
  840. $table_keys = array();
  841. $titles = $result_file->get_test_titles();
  842. foreach($titles as $this_title_index => $this_title)
  843. {
  844. if($this_title == $titles[$key])
  845. {
  846. array_push($table_keys, $this_title_index);
  847. }
  848. }
  849. }
  850. else
  851. {
  852. $table_keys = $key;
  853. }
  854. $chart = new pts_ResultFileTable($result_file, null, $table_keys);
  855. $chart->renderChart($save_to_dir . '/result-graphs/' . ($key + 1) . '_table.BILDE_EXTENSION');
  856. unset($chart);
  857. $generated_graph_tables = true;
  858. }
  859. }
  860. $graph = pts_render::render_graph($result_object, $result_file, $save_to);
  861. array_push($generated_graphs, $graph);
  862. }
  863. // Generate mini / overview graphs
  864. if($save_to_dir)
  865. {
  866. $graph = new pts_OverviewGraph($result_file);
  867. if($graph->doSkipGraph() == false)
  868. {
  869. $graph->renderGraph();
  870. // Check to see if skip_graph was realized during the rendering process
  871. if($graph->doSkipGraph() == false)
  872. {
  873. $graph->svg_dom->output($save_to_dir . '/result-graphs/visualize.BILDE_EXTENSION');
  874. }
  875. }
  876. unset($graph);
  877. $graph = new pts_RadarOverviewGraph($result_file);
  878. if($graph->doSkipGraph() == false)
  879. {
  880. $graph->renderGraph();
  881. // Check to see if skip_graph was realized during the rendering process
  882. if($graph->doSkipGraph() == false)
  883. {
  884. $graph->svg_dom->output($save_to_dir . '/result-graphs/radar.BILDE_EXTENSION');
  885. }
  886. }
  887. unset($graph);
  888. /*
  889. // TODO XXX: just stuffing some debug code here temporarily while working on block diagram code...
  890. $graph = new pts_BlockDiagramGraph($result_file);
  891. $graph->renderGraph();
  892. $graph->svg_dom->output($save_to_dir . '/result-graphs/blocks.BILDE_EXTENSION');
  893. */
  894. }
  895. // Save XSL
  896. if(count($generated_graphs) > 0 && $save_to_dir)
  897. {
  898. file_put_contents($save_to_dir . '/pts-results-viewer.xsl', pts_client::xsl_results_viewer_graph_template($generated_graph_tables));
  899. }
  900. return $generated_graphs;
  901. }
  902. public static function process_shutdown_tasks()
  903. {
  904. // TODO: possibly do something like posix_getpid() != pts_client::$startup_pid in case shutdown function is called from a child process
  905. // Generate Phodevi Smart Cache
  906. if(pts_flags::no_phodevi_cache() == false && pts_client::read_env('EXTERNAL_PHODEVI_CACHE') == false)
  907. {
  908. if(pts_config::read_bool_config('PhoronixTestSuite/Options/General/UsePhodeviCache', 'TRUE'))
  909. {
  910. pts_storage_object::set_in_file(PTS_CORE_STORAGE, 'phodevi_smart_cache', phodevi::get_phodevi_cache_object(PTS_USER_PATH, PTS_CORE_VERSION));
  911. }
  912. else
  913. {
  914. pts_storage_object::set_in_file(PTS_CORE_STORAGE, 'phodevi_smart_cache', null);
  915. }
  916. }
  917. if(is_array(self::$lock_pointers))
  918. {
  919. foreach(array_keys(self::$lock_pointers) as $lock_file)
  920. {
  921. self::release_lock($lock_file);
  922. }
  923. }
  924. foreach(self::$forked_pids as $pid)
  925. {
  926. if(is_dir('/proc/' . $pid) && function_exists('posix_kill'))
  927. {
  928. posix_kill($pid, SIGKILL);
  929. }
  930. }
  931. }
  932. public static function do_anonymous_usage_reporting()
  933. {
  934. return pts_config::read_bool_config('PhoronixTestSuite/Options/OpenBenchmarking/AnonymousUsageReporting', 0);
  935. }
  936. public static function release_lock($lock_file)
  937. {
  938. // Remove lock
  939. if(isset(self::$lock_pointers[$lock_file]) == false)
  940. {
  941. return false;
  942. }
  943. if(is_resource(self::$lock_pointers[$lock_file]))
  944. {
  945. fclose(self::$lock_pointers[$lock_file]);
  946. }
  947. pts_file_io::unlink($lock_file);
  948. unset(self::$lock_pointers[$lock_file]);
  949. }
  950. public static function check_command_for_function($option, $check_function)
  951. {
  952. $in_option = false;
  953. if(is_file(PTS_COMMAND_PATH . $option . '.php'))
  954. {
  955. if(!class_exists($option, false) && is_file(PTS_COMMAND_PATH . $option . '.php'))
  956. {
  957. include(PTS_COMMAND_PATH . $option . '.php');
  958. }
  959. if(method_exists($option, $check_function))
  960. {
  961. $in_option = true;
  962. }
  963. }
  964. return $in_option;
  965. }
  966. public static function regenerate_graphs($result_file_identifier, $full_process_string = false, $extra_graph_attributes = null)
  967. {
  968. $save_to_dir = pts_client::setup_test_result_directory($result_file_identifier);
  969. $generated_graphs = pts_client::generate_result_file_graphs($result_file_identifier, $save_to_dir, false, $extra_graph_attributes);
  970. $generated = count($generated_graphs) > 0;
  971. if($generated && $full_process_string)
  972. {
  973. echo PHP_EOL . $full_process_string . PHP_EOL;
  974. pts_client::display_web_page(PTS_SAVE_RESULTS_PATH . $result_file_identifier . '/index.html');
  975. }
  976. return $generated;
  977. }
  978. public static function set_test_flags($test_flags = 0)
  979. {
  980. pts_c::$test_flags = $test_flags;
  981. }
  982. public static function execute_command($command, $pass_args = null)
  983. {
  984. if(!class_exists($command, false) && is_file(PTS_COMMAND_PATH . $command . '.php'))
  985. {
  986. include(PTS_COMMAND_PATH . $command . '.php');
  987. }
  988. if(is_file(PTS_COMMAND_PATH . $command . '.php') && method_exists($command, 'argument_checks'))
  989. {
  990. $argument_checks = call_user_func(array($command, 'argument_checks'));
  991. foreach($argument_checks as &$argument_check)
  992. {
  993. $function_check = $argument_check->get_function_check();
  994. $method_check = false;
  995. if(is_array($function_check) && count($function_check) == 2)
  996. {
  997. $method_check = $function_check[0];
  998. $function_check = $function_check[1];
  999. }
  1000. if(substr($function_check, 0, 1) == '!')
  1001. {
  1002. $function_check = substr($function_check, 1);
  1003. $return_fails_on = true;
  1004. }
  1005. else
  1006. {
  1007. $return_fails_on = false;
  1008. }
  1009. if($method_check != false)
  1010. {
  1011. if(!method_exists($method_check, $function_check))
  1012. {
  1013. echo PHP_EOL . 'Method check fails.' . PHP_EOL;
  1014. continue;
  1015. }
  1016. $function_check = array($method_check, $function_check);
  1017. }
  1018. else if(!function_exists($function_check))
  1019. {
  1020. continue;
  1021. }
  1022. if($argument_check->get_argument_index() == 'VARIABLE_LENGTH')
  1023. {
  1024. $return_value = null;
  1025. foreach($pass_args as $arg)
  1026. {
  1027. $return_value = call_user_func_array($function_check, array($arg));
  1028. if($return_value == true)
  1029. {
  1030. break;
  1031. }
  1032. }
  1033. }
  1034. else
  1035. {
  1036. $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)));
  1037. }
  1038. if($return_value == $return_fails_on)
  1039. {
  1040. $command_alias = defined($command . '::doc_use_alias') ? constant($command . '::doc_use_alias') : $command;
  1041. 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)))
  1042. {
  1043. trigger_error('Invalid Argument: ' . implode(' ', $pass_args), E_USER_ERROR);
  1044. }
  1045. else
  1046. {
  1047. trigger_error('Phoronix Test Suite Argument Missing.', E_USER_ERROR);
  1048. }
  1049. echo PHP_EOL . 'CORRECT SYNTAX:' . PHP_EOL . 'phoronix-test-suite ' . str_replace('_', '-', $command_alias) . ' ' . implode(' ', $argument_checks) . PHP_EOL . PHP_EOL;
  1050. if(method_exists($command, 'invalid_command'))
  1051. {
  1052. call_user_func_array(array($command, 'invalid_command'), $pass_args);
  1053. echo PHP_EOL;
  1054. }
  1055. return false;
  1056. }
  1057. else
  1058. {
  1059. if($argument_check->get_function_return_key() != null && !isset($pass_args[$argument_check->get_function_return_key()]))
  1060. {
  1061. $pass_args[$argument_check->get_function_return_key()] = $return_value;
  1062. }
  1063. }
  1064. }
  1065. }
  1066. pts_module_manager::module_process('__pre_option_process', $command);
  1067. if(is_file(PTS_COMMAND_PATH . $command . '.php'))
  1068. {
  1069. self::$current_command = $command;
  1070. if(method_exists($command, 'run'))
  1071. {
  1072. call_user_func(array($command, 'run'), $pass_args);
  1073. }
  1074. else
  1075. {
  1076. echo PHP_EOL . 'There is an error in the requested command: ' . $command . PHP_EOL . PHP_EOL;
  1077. }
  1078. }
  1079. else if(($t = pts_module::valid_run_command($command)) != false)
  1080. {
  1081. list($module, $module_command) = $t;
  1082. pts_module_manager::set_current_module($module);
  1083. pts_module_manager::run_command($module, $module_command, $pass_args);
  1084. pts_module_manager::set_current_module(null);
  1085. }
  1086. echo PHP_EOL;
  1087. pts_module_manager::module_process('__post_option_process', $command);
  1088. }
  1089. public static function current_command()
  1090. {
  1091. return self::$current_command;
  1092. }
  1093. public static function terminal_width()
  1094. {
  1095. static $terminal_width = null;
  1096. if($terminal_width == null)
  1097. {
  1098. $chars = 80;
  1099. if(pts_client::read_env('TERMINAL_WIDTH') != false && is_numeric(pts_client::read_env('TERMINAL_WIDTH')) >= 80)
  1100. {
  1101. $terminal_width = pts_client::read_env('TERMINAL_WIDTH');
  1102. }
  1103. else if(pts_client::executable_in_path('stty'))
  1104. {
  1105. $terminal_width = explode(' ', trim(shell_exec('stty size 2>&1')));
  1106. if(count($terminal_width) == 2 && is_numeric($terminal_width[1]) && $terminal_width[1] >= 80)
  1107. {
  1108. $chars = $terminal_width[1];
  1109. }
  1110. }
  1111. else if(pts_client::executable_in_path('tput'))
  1112. {
  1113. $terminal_width = trim(shell_exec('tput cols 2>&1'));
  1114. if(is_numeric($terminal_width) && $terminal_width > 1)
  1115. {
  1116. $chars = $terminal_width;
  1117. }
  1118. }
  1119. $terminal_width = $chars;
  1120. }
  1121. return $terminal_width;
  1122. }
  1123. public static function user_hardware_software_reporting()
  1124. {
  1125. $hw_reporting = pts_config::read_bool_config('PhoronixTestSuite/Options/OpenBenchmarking/AnonymousHardwareReporting', 'FALSE');
  1126. $sw_reporting = pts_config::read_bool_config('PhoronixTestSuite/Options/OpenBenchmarking/AnonymousSoftwareReporting', 'FALSE');
  1127. if($hw_reporting == false && $sw_reporting == false)
  1128. {
  1129. return;
  1130. }
  1131. $hw = array();
  1132. $sw = array();
  1133. $pso = pts_storage_object::recover_from_file(PTS_CORE_STORAGE);
  1134. if($hw_reporting)
  1135. {
  1136. $hw = array();
  1137. foreach(pts_openbenchmarking::stats_hardware_list() as $key => $value)
  1138. {
  1139. if(count($value) == 2)
  1140. {
  1141. $hw[$key] = phodevi::read_property($value[0], $value[1]);
  1142. }
  1143. else
  1144. {
  1145. $hw[$key] = phodevi::read_name($value[0]);
  1146. }
  1147. }
  1148. $hw_prev = $pso->read_object('global_reported_hw');
  1149. $pso->add_object('global_reported_hw', $hw);
  1150. if(is_array($hw_prev))
  1151. {
  1152. $hw = array_diff_assoc($hw, $hw_prev);
  1153. }
  1154. // Check the PCI devices
  1155. $pci = phodevi::read_property('motherboard', 'pci-devices');
  1156. $pci_prev = $pso->read_object('global_reported_pci');
  1157. $pso->add_object('global_reported_pci', $pci);
  1158. if(!empty($pci_prev) && is_array($pci_prev) && is_array($pci))
  1159. {
  1160. if($pci == $pci_prev)
  1161. {
  1162. $pci = null;
  1163. }
  1164. else
  1165. {
  1166. $pci = array_diff($pci, $pci_prev);
  1167. }
  1168. }
  1169. if(!empty($pci))
  1170. {
  1171. pts_openbenchmarking_client::upload_pci_data($pci);
  1172. }
  1173. // Check the USB devices
  1174. $usb = phodevi::read_property('motherboard', 'usb-devices');
  1175. $usb_prev = $pso->read_object('global_reported_usb');
  1176. $pso->add_object('global_reported_usb', $usb);
  1177. if(!empty($usb_prev) && is_array($usb_prev) && is_array($usb) && $usb != $usb_prev)
  1178. {
  1179. pts_openbenchmarking_client::upload_usb_data($usb);
  1180. }
  1181. }
  1182. if($sw_reporting)
  1183. {
  1184. $sw = array();
  1185. foreach(pts_openbenchmarking::stats_software_list() as $key => $value)
  1186. {
  1187. if(count($value) == 2)
  1188. {
  1189. $sw[$key] = phodevi::read_property($value[0], $value[1]);
  1190. }
  1191. else
  1192. {
  1193. $sw[$key] = phodevi::read_name($value[0]);
  1194. }
  1195. }
  1196. $sw_prev = $pso->read_object('global_reported_sw');
  1197. $pso->add_object('global_reported_sw', $sw);
  1198. if(is_array($sw_prev))
  1199. {
  1200. $sw = array_diff_assoc($sw, $sw_prev);
  1201. }
  1202. }
  1203. $to_report = array_merge($hw, $sw);
  1204. $pso->save_to_file(PTS_CORE_STORAGE);
  1205. if(!empty($to_report))
  1206. {
  1207. pts_openbenchmarking_client::upload_hwsw_data($to_report);
  1208. }
  1209. }
  1210. public static function is_process_running($process)
  1211. {
  1212. if(phodevi::is_linux())
  1213. {
  1214. // Checks if process is running on the system
  1215. $running = shell_exec('ps -C ' . strtolower($process) . ' 2>&1');
  1216. $running = trim(str_replace(array('PID', 'TTY', 'TIME', 'CMD'), '', $running));
  1217. }
  1218. else if(phodevi::is_solaris())
  1219. {
  1220. // Checks if process is running on the system
  1221. $ps = shell_exec('ps -ef 2>&1');
  1222. $running = strpos($ps, ' ' . strtolower($process)) != false ? 'TRUE' : null;
  1223. }
  1224. else if(pts_client::executable_in_path('ps') != false)
  1225. {
  1226. // Checks if process is running on the system
  1227. $ps = shell_exec('ps -ax 2>&1');
  1228. $running = strpos($ps, ' ' . strtolower($process)) != false ? 'TRUE' : null;
  1229. }
  1230. else
  1231. {
  1232. $running = null;
  1233. }
  1234. return !empty($running);
  1235. }
  1236. public static function parse_value_string_double_identifier($value_string)
  1237. {
  1238. // i.e. with PRESET_OPTIONS='stream.run-type=Add'
  1239. $values = array();
  1240. foreach(explode(';', $value_string) as $preset)
  1241. {
  1242. if(count($preset = pts_strings::trim_explode('=', $preset)) == 2)
  1243. {
  1244. $dot = strrpos($preset[0], '.');
  1245. if($dot !== false && ($test = substr($preset[0], 0, $dot)) != null && ($option = substr($preset[0], ($dot + 1))) != null)
  1246. {
  1247. $values[$test][$option] = $preset[1];
  1248. }
  1249. }
  1250. }
  1251. return $values;
  1252. }
  1253. public static function create_temporary_file()
  1254. {
  1255. return tempnam(pts_client::temporary_directory(), 'PTS');
  1256. }
  1257. public static function create_temporary_directory($prefix = null)
  1258. {
  1259. $tmpdir = pts_client::temporary_directory();
  1260. do
  1261. {
  1262. $randname = '/pts-' . $prefix . rand(0, 9999);
  1263. }
  1264. while(is_dir($tmpdir . $randname));
  1265. mkdir($tmpdir . $randname);
  1266. return $tmpdir . $randname . '/';
  1267. }
  1268. public static function temporary_directory()
  1269. {
  1270. if(PHP_VERSION_ID >= 50210)
  1271. {
  1272. $dir = sys_get_temp_dir();
  1273. }
  1274. else
  1275. {
  1276. $dir = '/tmp'; // Assume /tmp
  1277. }
  1278. return $dir;
  1279. }
  1280. public static function read_env($var)
  1281. {
  1282. return getenv($var);
  1283. }
  1284. public static function pts_set_environment_variable($name, $value)
  1285. {
  1286. // Sets an environmental variable
  1287. return getenv($name) == false && putenv($name . '=' . $value);
  1288. }
  1289. public static function shell_exec($exec, $extra_vars = null)
  1290. {
  1291. // Same as shell_exec() but with the PTS env variables added in
  1292. // Convert pts_client::environmental_variables() into shell export variable syntax
  1293. $var_string = '';
  1294. $extra_vars = ($extra_vars == null ? pts_client::environmental_variables() : array_merge(pts_client::environmental_variables(), $extra_vars));
  1295. foreach(array_keys($extra_vars) as $key)
  1296. {
  1297. $var_string .= 'export ' . $key . '=' . $extra_vars[$key] . ';';
  1298. }
  1299. $var_string .= ' ';
  1300. return shell_exec($var_string . $exec);
  1301. }
  1302. public static function executable_in_path($executable)
  1303. {
  1304. static $cache = null;
  1305. if(!isset($cache[$executable]))
  1306. {
  1307. $paths = pts_strings::trim_explode((phodevi::is_windows() ? ';' : ':'), (($path = pts_client::read_env('PATH')) == false ? '/usr/bin:/usr/local/bin' : $path));
  1308. $executable_path = false;
  1309. foreach($paths as $path)
  1310. {
  1311. $path = pts_strings::add_trailing_slash($path);
  1312. if(is_executable($path . $executable))
  1313. {
  1314. $executable_path = $path . $executable;
  1315. break;
  1316. }
  1317. }
  1318. $cache[$executable] = $executable_path;
  1319. }
  1320. return $cache[$executable];
  1321. }
  1322. public static function display_web_page($URL, $alt_text = null, $default_open = true, $auto_open = false)
  1323. {
  1324. if(((pts_c::$test_flags & pts_c::auto_mode) && $auto_open == false && $default_open == false) || (pts_client::read_env('DISPLAY') == false && pts_client::read_env('WAYLAND_DISPLAY') == false && phodevi::is_windows() == false && phodevi::is_macosx() == false) || defined('PHOROMATIC_PROCESS'))
  1325. {
  1326. return;
  1327. }
  1328. if($auto_open == false)
  1329. {
  1330. $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);
  1331. }
  1332. else
  1333. {
  1334. $view_results = true;
  1335. }
  1336. if($view_results)
  1337. {
  1338. static $browser = null;
  1339. if($browser == null)
  1340. {
  1341. $config_browser = pts_config::read_user_config('PhoronixTestSuite/Options/General/DefaultBrowser', null);
  1342. if($config_browser != null && (is_executable($config_browser) || ($config_browser = pts_client::executable_in_path($config_browser))))
  1343. {
  1344. $browser = $config_browser;
  1345. }
  1346. else if(phodevi::is_windows())
  1347. {
  1348. $windows_browsers = array(
  1349. 'C:\Program Files (x86)\Mozilla Firefox\firefox.exe',
  1350. 'C:\Program Files\Internet Explorer\iexplore.exe'
  1351. );
  1352. foreach($windows_browsers as $browser_test)
  1353. {
  1354. if(is_executable($browser_test))
  1355. {
  1356. $browser = $browser_test;
  1357. break;
  1358. }
  1359. }
  1360. if(substr($URL, 0, 1) == '\\')
  1361. {
  1362. $URL = 'file:///C:' . str_replace('/', '\\', $URL);
  1363. }
  1364. }
  1365. else
  1366. {
  1367. $possible_browsers = array('epiphany', 'firefox', 'mozilla', 'x-www-browser', 'open', 'xdg-open', 'iceweasel', 'konqueror');
  1368. foreach($possible_browsers as &$b)
  1369. {
  1370. if(($b = pts_client::executable_in_path($b)))
  1371. {
  1372. $browser = $b;
  1373. break;
  1374. }
  1375. }
  1376. }
  1377. }
  1378. if($browser != null)
  1379. {
  1380. shell_exec($browser . ' "' . $URL . '" 2> /dev/null &');
  1381. }
  1382. else
  1383. {
  1384. echo PHP_EOL . 'No Web Browser Found.' . PHP_EOL;
  1385. }
  1386. }
  1387. }
  1388. public static function cache_hardware_calls()
  1389. {
  1390. phodevi::system_hardware(true);
  1391. phodevi::supported_sensors();
  1392. phodevi::unsupported_sensors();
  1393. }
  1394. public static function cache_software_calls()
  1395. {
  1396. phodevi::system_software(true);
  1397. }
  1398. public static function remove_saved_result_file($identifier)
  1399. {
  1400. pts_file_io::delete(PTS_SAVE_RESULTS_PATH . $identifier, null, true);
  1401. }
  1402. public static function saved_test_results()
  1403. {
  1404. $results = array();
  1405. $ignore_ids = array();
  1406. foreach(pts_file_io::glob(PTS_SAVE_RESULTS_PATH . '*/composite.xml') as $result_file)
  1407. {
  1408. $identifier = basename(dirname($result_file));
  1409. if(!in_array($identifier, $ignore_ids))
  1410. {
  1411. array_push($results, $identifier);
  1412. }
  1413. }
  1414. return $results;
  1415. }
  1416. public static function timed_function($function, $function_parameters, $time, $continue_while_true_function = null, $continue_while_true_function_parameters)
  1417. {
  1418. if(($time < 0.5 && $time != -1) || $time > 300)
  1419. {
  1420. return;
  1421. }
  1422. if(function_exists('pcntl_fork'))
  1423. {
  1424. $current_pid = function_exists('posix_getpid') ? posix_getpid() : -1;
  1425. $pid = pcntl_fork();
  1426. if($pid == -1)
  1427. {
  1428. trigger_error('Could not fork ' . $function . '.', E_USER_ERROR);
  1429. }
  1430. else if($pid)
  1431. {
  1432. array_push(self::$forked_pids, $pid);
  1433. }
  1434. else
  1435. {
  1436. posix_setsid();
  1437. $loop_continue = true;
  1438. while($loop_continue && is_file(PTS_USER_LOCK) && ($continue_while_true_function === true || ($loop_continue = call_user_func_array($continue_while_true_function, $continue_while_true_function_parameters))))
  1439. {
  1440. call_user_func_array($function, $function_parameters);
  1441. if($time > 0)
  1442. {
  1443. sleep($time);
  1444. }
  1445. else if($time == -1)
  1446. {
  1447. $loop_continue = false;
  1448. }
  1449. if($current_pid != -1 && !is_dir('/proc/' . $current_pid))
  1450. {
  1451. exit;
  1452. }
  1453. clearstatcache();
  1454. }
  1455. posix_kill(posix_getpid(), SIGINT);
  1456. exit(0);
  1457. }
  1458. }
  1459. else
  1460. {
  1461. if(is_array($function))
  1462. {
  1463. $function = implode(':', $function);
  1464. }
  1465. trigger_error('php-pcntl must be installed for calling ' . $function . '.', E_USER_ERROR);
  1466. }
  1467. }
  1468. public static function fork($fork_function, $fork_function_parameters)
  1469. {
  1470. if(function_exis

Large files files are truncated, but you can click here to view the full file