| 1 |
<?php
|
| 2 |
// $Id: simpletestauto.module,v 1.26 2006/08/10 09:06:51 rokZlender Exp $
|
| 3 |
/*
|
| 4 |
* Created on 3.6.2006
|
| 5 |
*/
|
| 6 |
|
| 7 |
$path = drupal_get_path('module', 'simpletestauto');
|
| 8 |
if (file_exists("$path/simpletestauto.inc")) {
|
| 9 |
require_once "$path/simpletestauto.inc";
|
| 10 |
}
|
| 11 |
define('SIMPLETESTAUTO_NOT_TESTED', 0);
|
| 12 |
define('SIMPLETESTAUTO_IN_PROGRESS', 1);
|
| 13 |
define('SIMPLETESTAUTO_FINISHED', 2);
|
| 14 |
define('SIMPLETESTAUTO_PASS', 3);
|
| 15 |
define('SIMPLETESTAUTO_FAIL', 4);
|
| 16 |
define('SIMPLETESTAUTO_SUBMITED', 5);
|
| 17 |
|
| 18 |
|
| 19 |
/**
|
| 20 |
* Display help and module information
|
| 21 |
* @param section which section of the site we're displaying help
|
| 22 |
* @return help text for section
|
| 23 |
*/
|
| 24 |
function simpletestauto_help($section='') {
|
| 25 |
$output = "";
|
| 26 |
|
| 27 |
switch($section) {
|
| 28 |
case "admin/modules#description";
|
| 29 |
$output = t("Simpletest automation");
|
| 30 |
break;
|
| 31 |
}
|
| 32 |
|
| 33 |
return $output;
|
| 34 |
}
|
| 35 |
|
| 36 |
/**
|
| 37 |
* Valid permission for this module
|
| 38 |
*
|
| 39 |
*/
|
| 40 |
function simpletestauto_perm() {
|
| 41 |
return array('Access test automation', 'Administer test automation');
|
| 42 |
}
|
| 43 |
|
| 44 |
/**
|
| 45 |
* implementation of menu hook
|
| 46 |
*/
|
| 47 |
function simpletestauto_menu($may_cache) {
|
| 48 |
$items[] = array(
|
| 49 |
'path' => 'admin/settings/simpletestauto',
|
| 50 |
'title' => t('simpletestauto'),
|
| 51 |
'callback' => 'drupal_get_form',
|
| 52 |
'callback arguments' => array('simpletestauto_admin_settings'),
|
| 53 |
'access' => user_access('administer site configuration'),
|
| 54 |
'type' => MENU_NORMAL_ITEM,
|
| 55 |
);
|
| 56 |
return $items;
|
| 57 |
}
|
| 58 |
|
| 59 |
/**
|
| 60 |
* Implementation of hook_settings
|
| 61 |
*/
|
| 62 |
function simpletestauto_admin_settings() {
|
| 63 |
|
| 64 |
$form['simpletestauto_server_pwd'] = array(
|
| 65 |
'#type' => 'password_confirm',
|
| 66 |
'#title' => t('Automatic testing server password'),
|
| 67 |
'#default_value' => variable_get('simpletestauto_server_pwd', ''),
|
| 68 |
'#size' => 50,
|
| 69 |
'#description' => t('Testing server password.'),
|
| 70 |
);
|
| 71 |
$form['simpletestauto_patch_settings'] = array(
|
| 72 |
'#type' => 'fieldset',
|
| 73 |
'#title' => t('Patch server settings'),
|
| 74 |
'#description' => t('This are the settings for the server that will catch patches.'),
|
| 75 |
'#collapsible' => TRUE,
|
| 76 |
'#collapsed' => (variable_get('simpletestauto_catch_patch',0) ? FALSE : TRUE),
|
| 77 |
);
|
| 78 |
|
| 79 |
$form['simpletestauto_patch_settings']['simpletestauto_catch_patch'] = array(
|
| 80 |
'#type' => 'radios',
|
| 81 |
'#title' => t('Is this server used to catch paches'),
|
| 82 |
'#default_value' => variable_get('simpletestauto_catch_patch', 0),
|
| 83 |
'#options' => array('No', 'Yes'),
|
| 84 |
);
|
| 85 |
|
| 86 |
$form['simpletestauto_patch_settings']['simpletestauto_server_url'] = array(
|
| 87 |
'#type' => 'textfield',
|
| 88 |
'#title' => t('Automatic testing server url'),
|
| 89 |
'#default_value' => variable_get('simpletestauto_server_url', $base_url.'/xmlrpc.php'),
|
| 90 |
'#size' => 50,
|
| 91 |
'#maxlength' => 255,
|
| 92 |
'#description' => t('Url of the server that will handle request for automatic patch testing.'),
|
| 93 |
);
|
| 94 |
|
| 95 |
$form['simpletestauto_patch_settings']['simpletestauto_use_hook_nodeapi'] = array(
|
| 96 |
'#type' => 'checkbox',
|
| 97 |
'#title' => t('Do you want to use hook_nodeapi to catch new patches?'),
|
| 98 |
'#default_value' => variable_get('simpletestauto_use_hook_nodeapi', 0),
|
| 99 |
'#description' => t('Checking this box will cause every new patch attached to issue will be sent to automatic testing.'),
|
| 100 |
);
|
| 101 |
|
| 102 |
$form['simpletestauto_test_settings'] = array(
|
| 103 |
'#type' => 'fieldset',
|
| 104 |
'#title' => t('Test server settings'),
|
| 105 |
'#description' => t('This are the settings for test server they only have effect if this server is used as a testing server'),
|
| 106 |
'#collapsible' => TRUE,
|
| 107 |
'#collapsed' => (variable_get('simpletestauto_use_as_server',0) ? FALSE : TRUE),
|
| 108 |
);
|
| 109 |
|
| 110 |
$form['simpletestauto_test_settings']['simpletestauto_use_as_server'] = array(
|
| 111 |
'#type' => 'radios',
|
| 112 |
'#title' => t('Is this server used as testing server'),
|
| 113 |
'#default_value' => variable_get('simpletestauto_use_as_server', 0),
|
| 114 |
'#options' => array('No', 'Yes'),
|
| 115 |
);
|
| 116 |
|
| 117 |
$form['simpletestauto_test_settings']['simpletestauto_test_modules'] = array(
|
| 118 |
'#type' => 'textfield',
|
| 119 |
'#title' => t('Additional modules'),
|
| 120 |
'#size' => 30,
|
| 121 |
'#maxlength' => 64,
|
| 122 |
'#default_value' => variable_get('simpletestauto_test_modules', 'image'),
|
| 123 |
'#description' => t('Additional modules that will be checked out from cvs and tested. Modules must be separated with comma'),
|
| 124 |
);
|
| 125 |
|
| 126 |
$form['simpletestauto_test_settings']['simpletestauto_install_dir'] = array(
|
| 127 |
'#type' => 'textfield',
|
| 128 |
'#title' => t('Install dir'),
|
| 129 |
'#size' => 30,
|
| 130 |
'#maxlength' => 64,
|
| 131 |
'#default_value' => variable_get('simpletestauto_install_dir', '/var/www/html/test'),
|
| 132 |
'#description' => t('A directory on the server that will be used to store test instances apache must have permission to write in this directory and it has to be accesible by web. Without trailing slash.'),
|
| 133 |
);
|
| 134 |
|
| 135 |
$form['simpletestauto_test_settings']['simpletestauto_test_url'] = array(
|
| 136 |
'#type' => 'textfield',
|
| 137 |
'#title' => t('Test server url'),
|
| 138 |
'#size' => 30,
|
| 139 |
'#maxlength' => 64,
|
| 140 |
'#default_value' => variable_get('simpletestauto_test_url', 'http://www.example.com/test/'),
|
| 141 |
'#description' => t('Url of install dir. With trailing slash'),
|
| 142 |
);
|
| 143 |
|
| 144 |
return system_settings_form($form);
|
| 145 |
}
|
| 146 |
|
| 147 |
/**
|
| 148 |
* Settings form validation
|
| 149 |
*/
|
| 150 |
function simpletestauto_admin_settings_validate($form_id, &$form_values) {
|
| 151 |
if ($form_values['simpletestauto_catch_patch'] == 1) {
|
| 152 |
// if(!valid_url($form_values['simpletestauto_server_url'], TRUE)) {
|
| 153 |
// form_set_error('simpletestauto_server_url', t('Automatic testing server url should be a valid url.'));
|
| 154 |
// }
|
| 155 |
}
|
| 156 |
if ($form_values['simpletestauto_use_as_server'] == 1) {
|
| 157 |
if(!valid_url($form_values['simpletestauto_test_url'], TRUE)) {
|
| 158 |
form_set_error('simpletestauto_test_url', t('Test url should be a valid url.'));
|
| 159 |
}
|
| 160 |
file_check_directory($form_values['simpletestauto_install_dir'], 0, 'simpletestauto_install_dir');
|
| 161 |
}
|
| 162 |
}
|
| 163 |
|
| 164 |
/**
|
| 165 |
* Implementation of hook_nodeapi
|
| 166 |
* Used of project server side to catch new patch submited.
|
| 167 |
*/
|
| 168 |
function simpletestauto_nodeapi(&$node, $op,$teaser = NULL, $page = NULL) {
|
| 169 |
if (variable_get('simpletestauto_use_hook_nodeapi', 0)) {
|
| 170 |
$server_url = variable_get('simpletestauto_server_url', '$base_url/xmlrpc.php');
|
| 171 |
$server_pwd = sha1(variable_get('simpletestauto_server_pwd', ''));
|
| 172 |
$r =0;
|
| 173 |
switch ($op) {
|
| 174 |
case 'update':
|
| 175 |
$r = $node->nid;
|
| 176 |
break;
|
| 177 |
case 'insert':
|
| 178 |
if ($node->type == "project_issue" && $node->file->filemime == "text/plain") {
|
| 179 |
$patchurl = file_create_url($node->file->filepath);
|
| 180 |
$n->nid = $node->pid;
|
| 181 |
$project = project_project_load($n);
|
| 182 |
$result = xmlrpc($server_url, 'simpletestauto.testPatch', $server_pwd, $patchurl, $project->uri);
|
| 183 |
if (is_string($result) && !stristr($result,'Error')) {
|
| 184 |
$msg = "Your patch test details can be found at ".l($result, $result);
|
| 185 |
$node->body = $node->body."<br />".$msg;
|
| 186 |
db_query("UPDATE {node_revisions} SET body = '%s' WHERE nid = %d",$node->body,$node->nid);
|
| 187 |
}
|
| 188 |
}
|
| 189 |
break;
|
| 190 |
default:
|
| 191 |
break;
|
| 192 |
}
|
| 193 |
}
|
| 194 |
}
|
| 195 |
|
| 196 |
/**
|
| 197 |
* Implementation of hook_form_alter
|
| 198 |
* Used to unset password fields if they are empty
|
| 199 |
*/
|
| 200 |
function simpletestauto_form_alter($form_id, &$form) {
|
| 201 |
if($_POST['edit']['form_id'] == "simpletestauto_admin_settings") {
|
| 202 |
$edit = $_POST['edit'];
|
| 203 |
if ($edit['simpletestauto_server_pwd']['pass1'] == $edit['simpletestauto_server_pwd']['pass2'] && $edit['simpletestauto_server_pwd']['pass1'] == "") {
|
| 204 |
unset($form['simpletestauto_server_pwd']);
|
| 205 |
}
|
| 206 |
if ($edit['simpletestauto_db_pass']['pass1'] == $edit['simpletestauto_db_pass']['pass2'] && $edit['simpletestauto_server_pwd']['pass1'] == "") {
|
| 207 |
unset($form['simpletestauto_test_settings']['simpletestauto_db_pass']);
|
| 208 |
}
|
| 209 |
}
|
| 210 |
}
|
| 211 |
|
| 212 |
function simpletestauto_node_info() {
|
| 213 |
return array('simpletestauto_test' => array('name' => t('Test instance'),'module' => 'simpletestauto_test', 'base' => 'simpletestauto_test'));
|
| 214 |
}
|
| 215 |
|
| 216 |
/**
|
| 217 |
* Implementation of hook_xmlrpc
|
| 218 |
* Used on testserver side to receive
|
| 219 |
*/
|
| 220 |
function simpletestauto_xmlrpc() {
|
| 221 |
if (variable_get('simpletestauto_use_as_server', '0')) {
|
| 222 |
return array('simpletestauto.testPatch' => 'simpletestauto_testPatch');
|
| 223 |
}
|
| 224 |
}
|
| 225 |
|
| 226 |
/**
|
| 227 |
* Implementation of hook_cron
|
| 228 |
* used to delete old tests only on testing server
|
| 229 |
*/
|
| 230 |
function simpletestauto_cron() {
|
| 231 |
if (variable_get('simpletestauto_use_as_server', '0')) {
|
| 232 |
$test_dir = variable_get('simpletestauto_install_dir','');
|
| 233 |
$db_user = variable_get('simpletestauto_db_user_name', '');
|
| 234 |
$db_pass = variable_get('simpletestauto_db_pass', '');
|
| 235 |
$dirs = file_scan_directory($test_dir, '\.clean$');
|
| 236 |
$removed_strings = array($test_dir, '.clean');
|
| 237 |
foreach($dirs as $instance_dir) {
|
| 238 |
$dir = $instance_dir->filename;
|
| 239 |
$instance = trim(str_replace($removed_strings,'',$dir),'/');
|
| 240 |
$exec_cmd = "mysqladmin -f -u $db_user -p$db_pass drop $instance";
|
| 241 |
exec($exec_cmd, $output, $status);
|
| 242 |
$exec_cmd = "rm -rf $test_dir/$instance";
|
| 243 |
exec($exec_cmd, $output, $status);
|
| 244 |
}
|
| 245 |
}
|
| 246 |
}
|
| 247 |
|
| 248 |
/**
|
| 249 |
* Implementation of hook_user().
|
| 250 |
*/
|
| 251 |
function simpletestauto_user($type, $edit, &$account, $category = NULL) {
|
| 252 |
global $user;
|
| 253 |
|
| 254 |
switch ($type) {
|
| 255 |
case 'form':
|
| 256 |
if($category == 'simpletestauto') {
|
| 257 |
|
| 258 |
$form['simpletestatuo'] = array(
|
| 259 |
'#type' => 'fieldset',
|
| 260 |
'#title' => t('Test automation account settings'),
|
| 261 |
'#weight' => 6,
|
| 262 |
'#collapsible' => TRUE,
|
| 263 |
'#collapsed' => FALSE,
|
| 264 |
);
|
| 265 |
if (user_access('Administer test automation')) {
|
| 266 |
$form['simpletestatuo']['simpletestauto_status'] = array(
|
| 267 |
'#type' => 'radios',
|
| 268 |
'#title' => t('Test automation status'),
|
| 269 |
'#default_value' => $simpletestauto_status,
|
| 270 |
'#options' => array(SIMPLETESTAUTO_PENDING => t('Pending'), SIMPLETESTAUTO_DENIED => t('Declined / Disabled'), SIMPLETESTATUO_APPROVED => t('Approved')),
|
| 271 |
'#description' => t("You can change the status of the user's test automation account."),
|
| 272 |
);
|
| 273 |
$form['simpletestatuo']['send_mail'] = array(
|
| 274 |
'#type' => 'checkbox',
|
| 275 |
'#title' => t('Inform the user by e-mail.'),
|
| 276 |
'#default_value' => 1,
|
| 277 |
);
|
| 278 |
$form['simpletestatuo']['message'] = array(
|
| 279 |
'#type' => 'textarea',
|
| 280 |
'#title' => t('Reason/Message'),
|
| 281 |
'#cols' => 50,
|
| 282 |
'#rows' => 5,
|
| 283 |
'#description' => t('The message you want to send to the user. This can be the reason for declining the application or an additional message after approval (used in e-mail).'),
|
| 284 |
);
|
| 285 |
}
|
| 286 |
return $form;
|
| 287 |
}
|
| 288 |
break;
|
| 289 |
case 'categories':
|
| 290 |
return array(array('name' => 'simpletestauto', 'title' => t('Test automation'), 'weight' => 4));
|
| 291 |
}
|
| 292 |
}
|
| 293 |
|
| 294 |
/**
|
| 295 |
* XML-rpc handler used on testserver side.
|
| 296 |
* It receives request to test a patch creates a node and returns this node id back to project server.
|
| 297 |
* And it runs a script that will run the tests.
|
| 298 |
*/
|
| 299 |
function simpletestauto_testPatch($password, $patch_url, $project_name, $version = "HEAD") {
|
| 300 |
global $base_url;
|
| 301 |
if ( $password == sha1(variable_get('simpletestauto_server_pwd', ''))) {
|
| 302 |
$node = new stdClass();
|
| 303 |
$node->title = "Testing $patch_url for $project_name";
|
| 304 |
$node->body = format_date(time(), 'large')."<br> Test is in test queue.";
|
| 305 |
$node->teaser = $node->body;
|
| 306 |
$node->log = "";
|
| 307 |
$node->type = "simpletestauto_test";
|
| 308 |
$node->format = "1";
|
| 309 |
$node->status = "1";
|
| 310 |
$node->project = $project_name;
|
| 311 |
$node->patch_url = $patch_url;
|
| 312 |
$node->version = $version;
|
| 313 |
$node->tested = 0;
|
| 314 |
node_save($node);
|
| 315 |
$new_url = url('node/'.$node->nid, NULL, NULL, TRUE);
|
| 316 |
return $new_url;
|
| 317 |
}
|
| 318 |
else {
|
| 319 |
return "Error: Wrong simpletestauto server password please check your settings";
|
| 320 |
}
|
| 321 |
}
|
| 322 |
|
| 323 |
/**
|
| 324 |
* Writes date and msg to the end of node body.
|
| 325 |
* @param $nid id of the node
|
| 326 |
* @param $msg msg that we want to append to the node
|
| 327 |
*/
|
| 328 |
function simpletestauto_writeResult($nid, $msg, $status) {
|
| 329 |
$node = node_load($nid);
|
| 330 |
$node->body .= "<br>".format_date(time(), 'large')."<br>".$msg;
|
| 331 |
if ( $status == 0) {
|
| 332 |
$node->tested = SIMPLETESTAUTO_PASS;
|
| 333 |
}
|
| 334 |
else {
|
| 335 |
$node->tested = SIMPLETESTAUTO_FAIL;
|
| 336 |
}
|
| 337 |
node_save($node);
|
| 338 |
return true;
|
| 339 |
}
|
| 340 |
|
| 341 |
/**
|
| 342 |
* Implementation of hook_block
|
| 343 |
* Displays test block on project server used for manual patch testing.
|
| 344 |
*/
|
| 345 |
function simpletestauto_block($op='list', $delta=0) {
|
| 346 |
$r = 0;
|
| 347 |
if ($op == 'list') {
|
| 348 |
$block[0]["info"] = t("Test your patch");
|
| 349 |
return $block;
|
| 350 |
}
|
| 351 |
else if ($op == 'view') {
|
| 352 |
$block = array();
|
| 353 |
$block['subject'] = t('Test your patch');
|
| 354 |
$block['content'] = drupal_get_form('patch_test_block_form');
|
| 355 |
return $block;
|
| 356 |
}
|
| 357 |
}
|
| 358 |
|
| 359 |
/**
|
| 360 |
* Patch test block form builder function
|
| 361 |
*/
|
| 362 |
function patch_test_block_form() {
|
| 363 |
|
| 364 |
$projects['Drupal'] = 'Drupal core';
|
| 365 |
$projects['project'] = 'Project module';
|
| 366 |
$projects['og'] = 'OG module';
|
| 367 |
$versions['HEAD'] = 'Head';
|
| 368 |
$versions['4.7'] = 'Drupal 4.7';
|
| 369 |
$versions['5'] = 'Drupal 5';
|
| 370 |
$form['patch_project'] = array(
|
| 371 |
'#type' => 'select',
|
| 372 |
'#title' => t('Which project is patch for?'),
|
| 373 |
'#default_value' => 'Drupal core',
|
| 374 |
'#options' => $projects,
|
| 375 |
'#required' => TRUE,
|
| 376 |
);
|
| 377 |
$form['project_version'] = array(
|
| 378 |
'#type' => 'select',
|
| 379 |
'#title' => t('Which project version is patch for?'),
|
| 380 |
'#default_value' => '4.7',
|
| 381 |
'#options' => $versions,
|
| 382 |
'#required' => TRUE,
|
| 383 |
);
|
| 384 |
$form['patch_url'] = array('#type' => 'textfield',
|
| 385 |
'#title' => t('Patch url'),
|
| 386 |
'#size' => 20,
|
| 387 |
'#required' => TRUE,
|
| 388 |
);
|
| 389 |
$form['submit'] = array('#type' => 'submit',
|
| 390 |
'#value' => t('Test'),
|
| 391 |
);
|
| 392 |
return $form;
|
| 393 |
}
|
| 394 |
|
| 395 |
/**
|
| 396 |
* Function that handles form submit from simpletestauto block.
|
| 397 |
* It sends request to test server and displays drupal message.
|
| 398 |
*/
|
| 399 |
function patch_test_block_form_submit($form_id, $form_values) {
|
| 400 |
$server_url = variable_get('simpletestauto_server_url', '$base_url/xmlrpc.php');
|
| 401 |
$server_pwd = sha1(variable_get('simpletestauto_server_pwd', ''));
|
| 402 |
$msg = xmlrpc($server_url, 'simpletestauto.testPatch', $server_pwd, $form_values['patch_url'], $form_values['patch_project'], $form_values['project_version']);
|
| 403 |
if (stristr($msg,'Error')) {
|
| 404 |
drupal_set_message(t($msg), 'error');
|
| 405 |
}
|
| 406 |
else if ($msg) {
|
| 407 |
drupal_set_message(t('Your patch test progress can be monitored at ').l($msg, $msg));
|
| 408 |
}
|
| 409 |
else {
|
| 410 |
$err_no = xmlrpc_error_msg();
|
| 411 |
drupal_set_message(t('There was an error durring your request. Error: '.$err_no),'error');
|
| 412 |
}
|
| 413 |
}
|
| 414 |
?>
|