PageRenderTime 165ms CodeModel.GetById 50ms RepoModel.GetById 1ms app.codeStats 0ms

/phoronix-test-suite/pts-core/objects/client/pts_client.php

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