Compare commits

..

No commits in common. "master" and "v2.0.0" have entirely different histories.

7 changed files with 129 additions and 436 deletions

View File

@ -1,29 +0,0 @@
name: Publish PHP Package
on:
push:
tags:
- 'v*'
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Get tag name
run: echo "TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
- name: zip and send
run: |
ls -la
apt-get update -y
apt-get install -y zip
cd ../
zip -r ${{ gitea.event.repository.name }}.zip ${{ gitea.event.repository.name }} -x '*.git*'
curl -v \
--user composer-pbl:${{ secrets.COMPOSER_PSWD }} \
--upload-file ${{ gitea.event.repository.name }}.zip \
https://git.bit5.ru/api/packages/bit/composer?version=${{ env.TAG }}

View File

@ -114,17 +114,17 @@ function _try_lz4_replay(string $txt)
return "4:" . base64_encode(lz4_compress(base64_decode($txt))); return "4:" . base64_encode(lz4_compress(base64_decode($txt)));
} }
function log(string $msg) function log($msg)
{ {
echo date("Y-m-d H:i:s") . " " . $msg . "\n"; echo date("Y-m-d H:i:s") . " " . $msg . "\n";
} }
function err(string $msg) function err($msg)
{ {
taskman\stderr(date("Y-m-d H:i:s") . " " . $msg . "\n"); taskman\stderr(date("Y-m-d H:i:s") . " " . $msg . "\n");
} }
function _retry(int $max_tries, callable $func, int $sleep = 1) function _retry($max_tries, $func)
{ {
for($i=0;$i<$max_tries;++$i) for($i=0;$i<$max_tries;++$i)
{ {
@ -133,12 +133,12 @@ function _retry(int $max_tries, callable $func, int $sleep = 1)
$func(); $func();
return; return;
} }
catch(\Throwable $e) catch(Exception $e)
{ {
if(($i+1) == $max_tries) if(($i+1) == $max_tries)
throw $e; throw $e;
} }
sleep($sleep); sleep(1);
} }
} }
@ -179,28 +179,14 @@ function get_ext_status_async(string $atf_host, string $device, int $timeout = 2
}); });
} }
function stop_app_async(string $atf_host, string $device) : Amp\Promise
{
return Amp\call(function() use($atf_host, $device) {
yield host_exec_async($atf_host, "%{adb}% -s $device shell am force-stop %{package_id}%", DEPLOY_OPT_ERR_OK, 30);
});
}
function start_app_async(string $atf_host, string $device) : Amp\Promise
{
return Amp\call(function() use($atf_host, $device) {
yield host_exec_async($atf_host, "%{adb}% -s $device shell am start -n %{package_id}%/%{activity}%", 0, 30);
});
}
function start_ext_cmd_on_device_async(string $atf_host, string $device, Cmd $cmd, array $cmd_args) : Amp\Promise function start_ext_cmd_on_device_async(string $atf_host, string $device, Cmd $cmd, array $cmd_args) : Amp\Promise
{ {
return Amp\call(function() use($atf_host, $device, $cmd, $cmd_args) { return Amp\call(function() use($atf_host, $device, $cmd, $cmd_args) {
yield device_del_file_async($atf_host, $device, 'atf_status.js', DEPLOY_OPT_ERR_OK); yield device_del_file_async($atf_host, $device, 'atf_status.js', DEPLOY_OPT_ERR_OK);
yield stop_app_async($atf_host, $device); yield host_exec_async($atf_host, "%{adb}% -s $device shell am force-stop %{package_id}%", DEPLOY_OPT_ERR_OK, 30);
yield update_ext_cmd_async($atf_host, $device, $cmd, $cmd_args); yield update_ext_cmd_async($atf_host, $device, $cmd, $cmd_args);
yield start_app_async($atf_host, $device); yield host_exec_async($atf_host, "%{adb}% -s $device shell am start -n %{package_id}%/%{activity}%", 0, 30);
}); });
} }
@ -396,6 +382,22 @@ function _multi_curl_async($ch, $get_content) : Amp\Promise
}); });
} }
function device_screen(string $atf_host, string $device)
{
$screen_file_name = '%{dir}%/'.uniqid("screen_").'.png';
try
{
host_exec($atf_host, "%{adb}% -s $device exec-out screencap -p > $screen_file_name");
}
catch(Exception $e)
{
return false;
}
$data = host_get_file($atf_host, $screen_file_name);
host_exec($atf_host, "rm -rf $screen_file_name");
return $data;
}
function del_external_files_async(string $atf_host, string $device, array $external_files) : Amp\Promise function del_external_files_async(string $atf_host, string $device, array $external_files) : Amp\Promise
{ {
return Amp\call(function() use($atf_host, $device, $external_files) { return Amp\call(function() use($atf_host, $device, $external_files) {
@ -467,3 +469,68 @@ function _filter_error_logs(array &$lines)
$lines = $filtered; $lines = $filtered;
} }
function device_pss_async(string $atf_host, string $device) : Amp\Promise
{
return Amp\call(function() use($atf_host, $device) {
$res = yield device_mem_async($atf_host, $device);
return $res['total'];
});
}
function device_mem_async(string $atf_host, string $device) : Amp\Promise
{
return Amp\call(function() use($atf_host, $device) {
list($code, $lines) = yield host_exec_async($atf_host, "%{adb}% -s $device shell dumpsys meminfo -s %{package_id}%", DEPLOY_OPT_ERR_OK, 20);
$res = array(
'total' => 0,
'native' => 0,
'java' => 0,
'system' => 0,
'graphics' => 0,
);
if($code !== 0)
return $res;
foreach($lines as $idx => $line)
{
$items = preg_split('/\s+/', trim($line));
if($items && $items[0] === "TOTAL:")
$res['total'] = intval($items[1]);
else if($items && $items[0] === "TOTAL" && $items[1] === "PSS:")
$res['total'] = intval($items[2]);
else if($items && $items[0] === "Native" && $items[1] === "Heap:")
$res['native'] = intval($items[2]);
else if($items && $items[0] === "Java" && $items[1] === "Heap:")
$res['java'] = intval($items[2]);
else if($items && $items[0] === "System:")
$res['system'] = intval($items[1]);
else if($items && $items[0] === "Graphics:")
$res['graphics'] = intval($items[1]);
}
return $res;
});
}
function device_temperature_async(string $atf_host, string $device) : Amp\Promise
{
return Amp\call(function() use($atf_host, $device) {
//NOTE: on current devices 16 thermal zone is responsible for GPU temperature probing
list($code, $lines) = yield host_exec_async($atf_host, "%{adb}% -s $device shell cat /sys/class/thermal/thermal_zone16/temp", DEPLOY_OPT_ERR_OK, 1);
if($code !== 0)
return 0;
foreach($lines as $idx => $line)
{
$line = trim($line);
if(!$line)
continue;
return intval($line);
}
return 0;
});
}

View File

@ -160,205 +160,3 @@ class CachedDevices implements IDevicePool
} }
} }
function device_screen(string $atf_host, string $device)
{
$screen_file_name = '%{dir}%/'.uniqid("screen_").'.png';
try
{
host_exec($atf_host, "%{adb}% -s $device exec-out screencap -p > $screen_file_name");
}
catch(Exception $e)
{
return false;
}
$data = host_get_file($atf_host, $screen_file_name);
host_exec($atf_host, "rm -rf $screen_file_name");
return $data;
}
function device_pss_async(string $atf_host, string $device) : Amp\Promise
{
return Amp\call(function() use($atf_host, $device) {
$res = yield device_mem_async($atf_host, $device);
return $res['total'];
});
}
function device_mem_async(string $atf_host, string $device) : Amp\Promise
{
return Amp\call(function() use($atf_host, $device) {
list($code, $lines) = yield host_exec_async($atf_host, "%{adb}% -s $device shell dumpsys meminfo -s %{package_id}%", DEPLOY_OPT_ERR_OK, 20);
$res = array(
'total' => 0,
'native' => 0,
'java' => 0,
'system' => 0,
'graphics' => 0,
);
if($code !== 0)
return $res;
foreach($lines as $idx => $line)
{
$items = preg_split('/\s+/', trim($line));
if($items && $items[0] === "TOTAL:")
$res['total'] = intval($items[1]);
else if($items && $items[0] === "TOTAL" && $items[1] === "PSS:")
$res['total'] = intval($items[2]);
else if($items && $items[0] === "Native" && $items[1] === "Heap:")
$res['native'] = intval($items[2]);
else if($items && $items[0] === "Java" && $items[1] === "Heap:")
$res['java'] = intval($items[2]);
else if($items && $items[0] === "System:")
$res['system'] = intval($items[1]);
else if($items && $items[0] === "Graphics:")
$res['graphics'] = intval($items[1]);
}
return $res;
});
}
function device_cpuinfo_async(string $atf_host, string $device) : Amp\Promise
{
return Amp\call(function() use($atf_host, $device) {
list($code, $lines) = yield host_exec_async($atf_host, "%{adb}% -s $device shell dumpsys cpuinfo -s %{package_id}%", DEPLOY_OPT_ERR_OK, 20);
$res = array(
'la1' => 0,
'la5' => 0,
'la15' => 0
);
if($code !== 0 || count($lines) == 0)
return $res;
foreach($lines as $idx => $line)
{
if(strpos($line, 'Load:') !== false)
{
$items = explode(':', $line);
$sub_items = explode('/', $items[1]);
$res['la1'] = floatval(trim($sub_items[0]));
$res['la5'] = floatval(trim($sub_items[1]));
$res['la15'] = floatval(trim($sub_items[2]));
break;
}
}
return $res;
});
}
function device_cputop_async(string $atf_host, string $device) : Amp\Promise
{
return Amp\call(function() use($atf_host, $device) {
list($code, $lines) = yield host_exec_async($atf_host, "%{adb}% -s $device shell top -q -o'%CPU,PID,CMDLINE' -n1 -s1 | grep -w %{package_id}%", DEPLOY_OPT_ERR_OK, 20);
$cpu = 0;
if($code !== 0 || count($lines) == 0)
return $cpu;
foreach($lines as $idx => $line)
{
$items = preg_split('/\s+/', trim($line));
if(count($items) > 0)
{
$cpu = intval($items[0]);
break;
}
}
return $cpu;
});
}
function device_cpu_freq_min_async(string $atf_host, string $device, int $core_index = 0) : Amp\Promise
{
return device_cpu_measure_async($atf_host, $device, "cpuinfo_min_freq", $core_index);
}
function device_cpu_freq_max_async(string $atf_host, string $device, int $core_index = 0) : Amp\Promise
{
return device_cpu_measure_async($atf_host, $device, "cpuinfo_max_freq", $core_index);
}
function device_cpu_freq_cur_async(string $atf_host, string $device, int $core_index = 0) : Amp\Promise
{
return device_cpu_measure_async($atf_host, $device, "scaling_cur_freq", $core_index);
}
function device_cpu_measure_async(string $atf_host, string $device, string $metric, int $core_index) : Amp\Promise
{
return Amp\call(function() use($atf_host, $device, $metric, $core_index) {
//NOTE: on current devices 16 thermal zone are responsible for GPU temperature probing
list($code, $lines) = yield host_exec_async($atf_host, "%{adb}% -s $device shell cat /sys/devices/system/cpu/cpu$core_index/cpufreq/$metric", DEPLOY_OPT_ERR_OK, 1);
if($code !== 0)
return 0;
foreach($lines as $idx => $line)
{
$line = trim($line);
if(!$line)
continue;
return intval($line);
}
return 0;
});
}
function device_temperature_async(string $atf_host, string $device) : Amp\Promise
{
return Amp\call(function() use($atf_host, $device) {
list($code, $lines) = yield host_exec_async($atf_host, "%{adb}% -s $device shell dumpsys thermalservice", DEPLOY_OPT_ERR_OK, 1);
if($code !== 0)
return array();
return device_parse_soc_temps($lines);
});
}
function device_parse_soc_temps($thermal_output_lines)
{
$cpu_temp = null;
$gpu_temp = null;
$hal_section_found = false;
foreach($thermal_output_lines as $line)
{
if(!$hal_section_found)
{
if(strpos($line, 'Current temperatures from HAL:') !== false)
$hal_section_found = true;
continue;
}
if(strpos($line, 'mType=0') !== false) //Type 0 indicates CPI
$cpu_temp = device_parse_thermal_line($line);
if(strpos($line, 'mType=1') !== false) //Type 1 indicates GPU
$gpu_temp = device_parse_thermal_line($line);
if($cpu_temp && $gpu_temp)
break;
}
return [
'cpu_temp' => $cpu_temp,
'gpu_temp' => $gpu_temp
];
}
function device_parse_thermal_line($line)
{
return preg_match('/mValue=([^,]+)/', $line, $matches) ? floatval($matches[1]) : null;
}

View File

@ -8,7 +8,6 @@ interface IMChan
{ {
function post(string $message, array $fields = array()) : array; function post(string $message, array $fields = array()) : array;
function updatePost(string $thread_id, array $fields = array()); function updatePost(string $thread_id, array $fields = array());
function postFile(string $title, string $mime_type, string $file_path, array $fields = array()) : array;
function postPNG(string $title, string $png_file, array $fields = array()) : array; function postPNG(string $title, string $png_file, array $fields = array()) : array;
function getPermalink(string $id) : string; function getPermalink(string $id) : string;
} }
@ -25,11 +24,6 @@ class NullMessenger implements IMChan
return array('ok' => true); return array('ok' => true);
} }
function postFile(string $title, string $mime_type, string $file_path, array $fields = array()) : array
{
return array('ok' => true);
}
function postPNG(string $title, string $png_file, array $fields = array()) : array function postPNG(string $title, string $png_file, array $fields = array()) : array
{ {
return array('ok' => true); return array('ok' => true);
@ -66,11 +60,6 @@ class MattermostChan implements IMChan
return mm_update($this->server, $this->token, $id, $fields); return mm_update($this->server, $this->token, $id, $fields);
} }
function postFile(string $title, string $mime_type, string $file_path, array $fields = array()) : array
{
return mm_post_file($this->server, $this->token, $this->chan, $title, $mime_type, $file_path, $fields);
}
function postPNG(string $title, string $png_file, array $fields = array()) : array function postPNG(string $title, string $png_file, array $fields = array()) : array
{ {
return mm_post_png($this->server, $this->token, $this->chan, $title, $png_file, $fields); return mm_post_png($this->server, $this->token, $this->chan, $title, $png_file, $fields);
@ -133,49 +122,7 @@ function mm_update(string $server, string $token, string $id, array $fields)
return json_decode($result, true); return json_decode($result, true);
} }
function mm_post_file( function mm_post_png(string $server, string $token, string $chan, string $title, string $png_file, $msg_fields = array())
string $server, string $token, string $chan,
string $title, string $mime_type, string $file_path,
$msg_fields = array()
)
{
$headers = array(
'Content-Type: multipart/form-data',
'Authorization: Bearer ' . $token
);
$file = new \CurlFile(realpath($file_path), $mime_type, basename($file_path));
$fields = array();
$fields['channel_id'] = $chan;
$fields['files'] = $file;
$ch = curl_init("$server/api/v4/files");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if($status != 201)
throw new Exception("File failed with status: " . $status .", result: " . var_export($result, true));
$result = json_decode($result, true);
$file_id = $result['file_infos'][0]['id'];
$msg_fields['file_ids'] = array($file_id);
return mm_post($server, $token, $chan, $title, $msg_fields);
}
function mm_post_png(
string $server, string $token, string $chan,
string $title, string $png_file,
$msg_fields = array()
)
{ {
$headers = array( $headers = array(
'Content-Type: multipart/form-data', 'Content-Type: multipart/form-data',

View File

@ -2,7 +2,6 @@
namespace ATF; namespace ATF;
use Exception; use Exception;
use Throwable;
use Amp; use Amp;
use taskman; use taskman;
@ -16,8 +15,6 @@ class Plan
const BOGUS_REINSTALL_APP_EVERY_N = 2; const BOGUS_REINSTALL_APP_EVERY_N = 2;
const IM_THREAD_UPDATE_INTERVAL = 5; const IM_THREAD_UPDATE_INTERVAL = 5;
const MaxImTextPostLen = 3000;
public Session $session; public Session $session;
public string $name; public string $name;
@ -248,22 +245,11 @@ class Plan
{ {
return Amp\call(function() use($task) { return Amp\call(function() use($task) {
if(!yield $this->_startAsync($task)) yield $this->_startAsync($task);
return;
while(!$this->isOver()) while(!$this->isOver())
{ {
try $this->_updateMessengerThread(false);
{
//let's not exit the testing just because we couldn't update IM thread for some reason
_retry(3, function() {
$this->_updateMessengerThread(false);
});
}
catch(\Throwable $e)
{
err("Task #{$task->run_id} IM thread update error: {$e} *{$task->device}*...");
}
yield Amp\delay((int)($this->session->conf->sleep_time*1000)); yield Amp\delay((int)($this->session->conf->sleep_time*1000));
@ -290,20 +276,13 @@ class Plan
{ {
//let's reset bogus stats for this device //let's reset bogus stats for this device
$this->session->resetBogusDeviceCount($task->device); $this->session->resetBogusDeviceCount($task->device);
//let's quit the application once the task is done
yield stop_app_async($this->session->conf->atf_host, $task->device);
//let's free the device //let's free the device
$task->device = null; $task->device = null;
break; break;
} }
} }
_retry(3, function() { $this->_updateMessengerThread(true);
$this->_updateMessengerThread(true);
}
);
}); });
} }
@ -335,7 +314,6 @@ class Plan
$task->getCmd(), $task->getCmd(),
$task->getCmdArgs() $task->getCmdArgs()
); );
$task->ext_cmd_start_time = time();
} }
catch(Exception $e) catch(Exception $e)
{ {
@ -350,7 +328,7 @@ class Plan
}); });
} }
function _ignoreDevice(string $device, string $reason) function _ignoreDevice($device, $reason)
{ {
$this->session->ignoreDevice($device, $reason); $this->session->ignoreDevice($device, $reason);
@ -370,11 +348,8 @@ class Plan
$this->_postScreenToMessenger($task); $this->_postScreenToMessenger($task);
if($task->getLastFatalProblem() == Task::CODE_EXCEPTION) if($task->getLastFatalProblem() == Task::CODE_EXCEPTION)
{
yield $this->_postLastReplayToMessengerAsync($task); yield $this->_postLastReplayToMessengerAsync($task);
}
else if($task->getLastFatalProblem() == Task::CODE_GONE || else if($task->getLastFatalProblem() == Task::CODE_GONE ||
$task->getLastFatalProblem() == Task::CODE_STUCK ||
$task->getLastFatalProblem() == Task::CODE_HUNG) $task->getLastFatalProblem() == Task::CODE_HUNG)
{ {
$app_log = get_logcat_unity($this->session->conf->atf_host, $task->device, 300); $app_log = get_logcat_unity($this->session->conf->atf_host, $task->device, 300);
@ -408,7 +383,7 @@ class Plan
yield $this->_checkExtStatusAsync($task, $timeout); yield $this->_checkExtStatusAsync($task, $timeout);
break; break;
} }
catch(Throwable $e) catch(Exception $e)
{ {
$last_error = $e->getMessage(); $last_error = $e->getMessage();
continue; continue;
@ -553,7 +528,7 @@ class Plan
static function _printToShellExtItem(Task $task, array $item) static function _printToShellExtItem(Task $task, array $item)
{ {
$shell_msg = _trim($item['message'], self::MaxImTextPostLen); $shell_msg = _trim($item['message'], 200);
if(Task::isProblemCode($item['error'])) if(Task::isProblemCode($item['error']))
$shell_msg = "[PRB] Code:{$item['error']}, $shell_msg"; $shell_msg = "[PRB] Code:{$item['error']}, $shell_msg";
$shell_msg = "(".round($item['time'],1)."s) {$shell_msg} *{$task->device}*"; $shell_msg = "(".round($item['time'],1)."s) {$shell_msg} *{$task->device}*";
@ -563,7 +538,7 @@ class Plan
function _postToMessengerExtStatusItem(Task $task, array $item) function _postToMessengerExtStatusItem(Task $task, array $item)
{ {
$orig_msg = _trim($item['message'], self::MaxImTextPostLen); $orig_msg = _trim($item['message'], 3000);
$mm_msg = $orig_msg; $mm_msg = $orig_msg;
if($item['error'] == Task::CODE_EXCEPTION) if($item['error'] == Task::CODE_EXCEPTION)
@ -583,30 +558,6 @@ class Plan
return $this->session->conf->im->post($msg, $args); return $this->session->conf->im->post($msg, $args);
} }
function postFileData(string $title, string $mime_type, string $file_data, string $file_extension, array $args = array()) : bool
{
$args['root_id'] = $this->im_thread_id;
if($file_data)
{
$tmp_file = tempnam(sys_get_temp_dir(), 'tmp_upload') . $file_extension;
taskman\ensure_write($tmp_file, $file_data);
try
{
$this->session->conf->im->postFile($title, $mime_type, $tmp_file, $args);
return true;
}
catch(Exception $e)
{}
finally
{
taskman\ensure_rm($tmp_file);
}
}
return false;
}
function _analyzeExtStatusItemAsync(Task $task, array $item) : Amp\Promise function _analyzeExtStatusItemAsync(Task $task, array $item) : Amp\Promise
{ {
return Amp\call(function() use($task, $item) { return Amp\call(function() use($task, $item) {
@ -637,15 +588,10 @@ class Plan
{ {
return Amp\call(function() use($task, $item, $msg_type, $msg_text) { return Amp\call(function() use($task, $item, $msg_type, $msg_text) {
if($item['error'] == Task::CODE_EXCEPTION || if($item['error'] == Task::CODE_EXCEPTION)
$item['error'] == Task::CODE_WARN)
{ {
$this->_postToMessengerExtStatusItem($task, $item); $this->_postToMessengerExtStatusItem($task, $item);
} }
else if($item['error'] == Task::CODE_RAW)
{
$this->_postRawDataToMessenger($task, $item['message']);
}
else if($msg_type === '[WRN]') else if($msg_type === '[WRN]')
{ {
$task->addStatusCode(Task::CODE_WARN); $task->addStatusCode(Task::CODE_WARN);
@ -680,27 +626,15 @@ class Plan
}); });
} }
function _postRawDataToMessenger(Task $task, string $txt)
{
if(strlen($txt) > self::MaxImTextPostLen)
$this->postFileData("Raw data: *{$task->device}*", 'text/plain', $txt, '.txt');
else
$this->post("Raw data: \n```\n$txt\n```\n *{$task->device}*");
}
function _postReplayToMessenger(Task $task, $repl_txt) function _postReplayToMessenger(Task $task, $repl_txt)
{ {
$repl_txt = _try_lz4_replay($repl_txt); $repl_txt = _try_lz4_replay($repl_txt);
$this->post("Last Replay: \n```\n$repl_txt\n```\n *{$task->device}*");
if(strlen($repl_txt) > self::MaxImTextPostLen)
$this->postFileData("Replay File: *{$task->device}*", 'text/plain', $repl_txt, '.txt');
else
$this->post("Last Replay: \n```\n$repl_txt\n```\n *{$task->device}*");
} }
function _reportErrorFromLogcatToMessenger(Task $task, $limit) function _reportErrorFromLogcatToMessenger(Task $task, $limit)
{ {
$errors_log = _trim(get_logcat_errors($this->session->conf->atf_host, $task->device, $limit), 3950); $errors_log = _trim(get_logcat_errors($task->device, $limit), 3950);
if($errors_log) if($errors_log)
$this->post("\n```\n$errors_log\n```\n *{$task->device}*"); $this->post("\n```\n$errors_log\n```\n *{$task->device}*");
} }

View File

@ -19,14 +19,13 @@ class SessionConfig
public bool $reboot_devices = false; public bool $reboot_devices = false;
public bool $error_pause = false; public bool $error_pause = false;
public int $sleep_time = 5; public int $sleep_time = 5;
public int $dead_threshold = 60; public int $dead_threshold = 80;
public int $stuck_threshold = 80; public int $stuck_threshold = 60;
public bool $share_with_qa_chan = true; public bool $share_with_qa_chan = true;
public IMChan $im; public IMChan $im;
public IMChan $im_qa; public IMChan $im_qa;
public IStatsSender $stats; public IStatsSender $stats;
public string $device_replay_path = 'replay.txt'; public string $device_replay_path = 'replay.txt';
public array $stats_event_listeners = array();
function __construct() function __construct()
{ {
@ -41,17 +40,11 @@ class SessionConfig
$this->atf_host = 'atf'; $this->atf_host = 'atf';
taskman\deploy_declare_node($this->atf_host, $settings); taskman\deploy_declare_node($this->atf_host, $settings);
} }
function registerStatsEventListener(callable $hook)
{
$this->stats_event_listeners[] = $hook;
}
} }
class Session class Session
{ {
const RUN_SLEEP = 3; const RUN_SLEEP = 3;
const IGNORE_DEVICE_TTL = 300;
public string $name; public string $name;
public SessionConfig $conf; public SessionConfig $conf;
@ -100,9 +93,8 @@ class Session
function getTitle() : string function getTitle() : string
{ {
$finished_plans = $this->countFinishedPlans(); return "Session ({$this->id}) '{$this->name}' (devices:".sizeof($this->getDevices())." ?:".sizeof($this->ignored_devices) .
return "**Session ({$this->id}) '{$this->name}' (plans:$finished_plans/".sizeof($this->plans)." devices:".sizeof($this->getDevices())." ?:".sizeof($this->ignored_devices) . ') (' . round($this->getDuration()/60, 1) . ' min)';
') (' . round($this->getDuration()/60, 1) . ' min)**';
} }
function getDuration() : int function getDuration() : int
@ -112,30 +104,18 @@ class Session
function getDevices() : array function getDevices() : array
{ {
$this->_checkIgnoredDevices(); $devices = array_diff(
$this->device_pool->get(),
$connected_devices = $this->device_pool->get(); $this->ignored_devices
$actual_devices = array_diff($connected_devices, array_keys($this->ignored_devices)); );
return $devices;
return $actual_devices;
}
function _checkIgnoredDevices()
{
//let's remove from ignored devices devices which were ignored for some time
$devices = array_keys($this->ignored_devices);
foreach($devices as $device)
{
if(time() - $this->ignored_devices[$device] > self::IGNORE_DEVICE_TTL)
unset($this->ignored_devices[$device]);
}
} }
function ignoreDevice(string $device, string $reason) function ignoreDevice(string $device, string $reason)
{ {
err("Ignoring device *$device*: $reason"); err("Ignoring device *$device*: $reason");
$this->ignored_devices[$device] = time(); $this->ignored_devices[] = $device;
} }
function incBogusDevice(string $device) function incBogusDevice(string $device)
@ -193,7 +173,6 @@ class Session
if($this->conf->adb_reboot) if($this->conf->adb_reboot)
adb_reboot($this->conf->atf_host); adb_reboot($this->conf->atf_host);
//TODO: should not be here
$this->trySendApkStatsEvent($this->apk_installer->getSize()); $this->trySendApkStatsEvent($this->apk_installer->getSize());
$all_tasks = $this->_getAllTasks(); $all_tasks = $this->_getAllTasks();
@ -298,9 +277,6 @@ class Session
//create new coroutines and assign them to free devices //create new coroutines and assign them to free devices
foreach($devices as $device) foreach($devices as $device)
{ {
if(!$device)
continue;
if(sizeof($tasks) == 0) if(sizeof($tasks) == 0)
break; break;
@ -388,15 +364,6 @@ class Session
return true; return true;
} }
function countFinishedPlans() : int
{
$n = 0;
foreach($this->plans as $plan)
if($plan->isOver())
$n++;
return $n;
}
function trySendStatsFromJzonAsync(Task $task, string $jzon) : Amp\Promise function trySendStatsFromJzonAsync(Task $task, string $jzon) : Amp\Promise
{ {
return Amp\call(function() use($task, $jzon) { return Amp\call(function() use($task, $jzon) {
@ -407,10 +374,9 @@ class Session
$table = $data['table']; $table = $data['table'];
unset($data['table']); unset($data['table']);
$data = yield $this->applyStatsEventsListeners($task, $table, $data); $data = yield $this->inflateMissingStats($task, $table, $data);
if($data !== null) $this->trySendStats($task, $table, $data);
$this->trySendStats($task, $table, $data);
} }
catch(Exception $e) catch(Exception $e)
{ {
@ -420,12 +386,27 @@ class Session
}); });
} }
function applyStatsEventsListeners(Task $task, string $table, array $data) : Amp\Promise //TODO: make it more flexible via plugin alike system?
function inflateMissingStats(Task $task, string $table, array $data) : Amp\Promise
{ {
return Amp\call(function() use($task, $table, $data) { return Amp\call(function() use($task, $table, $data) {
//NOTE: filling memory usage if it's not set
if(isset($data['deviceMemoryUsage']) && $data['deviceMemoryUsage'] === '')
{
$mem = yield device_mem_async($this->conf->atf_host, $task->device);
$data['deviceMemoryUsage'] = $mem['total'];
if($table === 'device_memory')
{
$data['deviceMemoryUsageNative'] = $mem['native'];
$data['deviceMemoryUsageSystem'] = $mem['system'];
$data['deviceMemoryUsageJava'] = $mem['java'];
$data['deviceMemoryUsageGraphics'] = $mem['graphics'];
}
}
foreach($this->conf->stats_event_listeners as $hook) //NOTE: filling CPU temperature
$data = yield $hook($this, $task, $table, $data); if(isset($data['event']) && $data['event'] == 'cpuTemp')
$data['value'] = yield device_temperature_async($this->conf->atf_host, $task->device);
return $data; return $data;
}); });
@ -435,7 +416,6 @@ class Session
{ {
try try
{ {
$data = array();
$data['guid'] = $this->guid; $data['guid'] = $this->guid;
$data['time'] = time(); $data['time'] = time();
$data['version'] = $this->conf->proj_version; $data['version'] = $this->conf->proj_version;

View File

@ -26,7 +26,6 @@ class Task
const CODE_MESSAGE = 0; const CODE_MESSAGE = 0;
const CODE_EXCEPTION = 1; const CODE_EXCEPTION = 1;
const CODE_WARN = 2; const CODE_WARN = 2;
const CODE_RAW = 3;
const CODE_NSTART = 124; const CODE_NSTART = 124;
const CODE_STUCK = 125; const CODE_STUCK = 125;
const CODE_GONE = 126; const CODE_GONE = 126;
@ -43,8 +42,6 @@ class Task
return "exception"; return "exception";
case self::CODE_WARN: case self::CODE_WARN:
return "warning"; return "warning";
case self::CODE_RAW:
return "raw";
case self::CODE_STUCK: case self::CODE_STUCK:
return "stuck"; return "stuck";
case self::CODE_NSTART: case self::CODE_NSTART:
@ -82,7 +79,6 @@ class Task
public float $start_time = 0; public float $start_time = 0;
public float $reset_time = 0; public float $reset_time = 0;
public float $ext_cmd_start_time = 0;
public float $last_progress = 0; public float $last_progress = 0;
public int $last_done_arg_idx = -1; public int $last_done_arg_idx = -1;