1<?php
2require_once(dirname(dirname(__FILE__)) . '/config.test.php');
3require_once(dirname(__FILE__) . '/simpletest/unit_tester.php');
4require_once(dirname(__FILE__) . '/simpletest/mock_objects.php');
5require_once(dirname(__FILE__) . '/simpletest/web_tester.php');
6require_once(dirname(__FILE__) . '/kw_db.php');
7require_once(dirname(__FILE__) . '/kw_unlink.php');
8
9
10/**
11 * The test manager interface kw tests with simpletest test.
12 *
13 * @package    kwtests
14 */
15class TestManager
16{
17  var $testDir  = null;
18  var $database = null;
19
20  function setDatabase($db){
21    $this->database = $db;
22  }
23
24  /**
25     * set the tests directory where the test files are placed
26     * @param string $dir
27     */
28  function setTestDirectory($dir){
29     $this->testDir = $dir;
30  }
31
32  /** Delete the log file */
33  function removeLogAndBackupFiles($logfilename)
34    {
35    if(file_exists($logfilename))
36      {
37      global $CDASH_TESTING_RENAME_LOGS;
38      if ($CDASH_TESTING_RENAME_LOGS)
39        {
40        // Rename to a random name to keep for later inspection:
41        //
42        global $CDASH_LOG_FILE;
43        rename($logfilename, $CDASH_LOG_FILE . "." . mt_rand() . ".txt");
44        }
45      else
46        {
47        // Delete file:
48        cdash_testsuite_unlink($logfilename);
49        }
50      }
51
52    $filenames = glob(dirname($logfilename)."/*.xml");
53    foreach($filenames as $filename)
54      {
55      cdash_testsuite_unlink($filename);
56      }
57    }
58  function runFileTest(&$reporter, $file)
59  {
60    $test = &new TestSuite('All Tests');
61    if($this->testDir !== null)
62      {
63      $path = $this->testDir.  "/" . $file;
64      }
65    else
66      {
67      $path = $file;
68      }
69    print "$path\n";
70    $test->addFile($path);
71    return $test->run($reporter);
72  }
73  /**
74     * run all the tests
75     * @return the result the test running
76     * @param object $reporter
77     */
78  function runAllTests(&$reporter) {
79    $testsFile = $this->getTestCaseList();
80    $test = &new TestSuite('All Tests');
81    foreach($testsFile as $path=>$file)
82      {
83      $test->addFile($path);
84      }
85    return $test->run($reporter);
86  }
87
88  /**
89     * Match all the test files inside the test directory
90     * @return an array of the test files
91     */
92  function getTestCaseList() {
93    if(!$this->testDir)
94      {
95      die ("please, set the test directory\n");
96      }
97    $testsFile = array();
98    foreach(glob($this->testDir.'/test_*.php') as $file)
99      {
100      $fileinfo = pathinfo($file);
101      if(strcmp($fileinfo['basename'],'test_install.php') != 0 &&
102         strcmp($fileinfo['basename'],'test_uninstall.php') != 0)
103        {
104        $testsFile[$fileinfo['dirname'].'/'.$fileinfo['basename']] = $fileinfo['basename'];
105        }
106      }
107    return $testsFile;
108  }
109
110
111  /**
112    * perform a connection to the database
113    * @return the result of the connection
114    * @param string $host
115    * @param string $user
116    * @param string $password
117    * @param string $dbname
118    * @param string $dbtype
119    * @access protected
120    */
121  function _connectToDb($host,$port,$user,$password,$dbname,$dbtype)
122  {
123    $database = new database($dbtype);
124    $database->setHost($host);
125    $database->setPort($port);
126    $database->setUser($user);
127    $database->setPassword($password);
128    $database->setDb($dbname);
129    return $database->connectedToDb();
130  }
131
132  /**
133     * drop the old test database
134     * @return success/failure depending of the database dropping
135     * @param string $host
136     * @param int $port
137     * @param string $user
138     * @param string $password
139     * @param string $dbname
140     * @param string $dbtype
141     * @access protected
142     */
143   function _uninstalldb4test($host,$port,$user,$password,$dbname,$dbtype)
144   {
145     if(!strcmp($dbname,'cdash4simpletest'))
146       {
147       $database = new database($dbtype);
148       $database->setHost($host);
149       $database->setPort($port);
150       $database->setUser($user);
151       $database->setPassword($password);
152       return $database->drop($dbname);
153       }
154    else
155      {
156      die("We cannot test cdash because test database is not cdash4simpletest\n");
157      }
158   }
159
160
161  /**
162     * create the new test database
163     * @return success/failure depending of the database creating
164     * @param string $host
165     * @param string $user
166     * @param string $password
167     * @param string $dbname
168     * @param string $dbtype
169     * @access protected
170     */
171  function _installdb4test($host,$port,$user,$password,$dbname,$dbtype)
172  {
173    if(!strcmp($dbname,'cdash4simpletest'))
174       {
175       $database = new database($dbtype);
176       $database->setHost($host);
177       $database->setPort($port);
178       $database->setUser($user);
179       $database->setPassword($password);
180       $dbcreated = true;
181       if(!$database->create($dbname))
182        {
183        $dbcreated = false;
184        $msg = 'error query(CREATE DATABASE)';
185        die("Error" . " File: " . __FILE__ . " on line: " . __LINE__.": $msg");
186        return false;
187        }
188      if($dbcreated)
189        {
190        $dirname = str_replace('\\','/',dirname(__FILE__));
191        $sqlfile = str_replace("/tests/kwtest","", $dirname)."/sql/".$dbtype."/cdash.sql";
192        $database->fillDb($sqlfile);
193        }
194      return true;
195       }
196    else
197      {
198      die("We cannot test cdash because test database is not cdash4simpletest\n");
199      }
200  }
201}
202
203
204
205/**
206 * The cdash test manager interface cdash test with simpletest
207 *
208 * @package    kwtests
209 */
210class CDashTestManager extends TestManager
211{
212   var $_urlToCdash = null;
213
214  /**
215     * run all the tests in the current directory
216     * @return the result of the test
217     * @param object $reporter
218     */
219   function runAllTests(&$reporter)
220     {
221     $reporter->paintTestCaseList($this->getTestCaseList());
222     parent::runAllTests($reporter);
223     }
224
225
226  /**
227     *    Set the url of the CDash server
228     *    @param string $url  url via we make the curl to send the report
229     */
230   function setCDashServer($servername){
231     if(!empty($servername))
232      {
233      $this->_urlToCdash = $servername;
234      }
235   }
236
237 /**
238    * update the svn repository
239    * @param object $reporter
240    * @param string $svnroot
241  */
242
243   function updateSVN($reporter,$svnroot,$type){
244      if(!empty($svnroot))
245       {
246       $reporter->paintUpdateStart();
247       $execution_time = $this->__performSvnUpdate($reporter,$svnroot,$type);
248       // The project is up to date and the type is Continuous
249       if(!$execution_time)
250         {
251         echo "error: updateSVN: false execution_time, no paintUpdateEnd\n";
252         return false;
253         }
254       // We put in minute the execution time of the svn update
255       if(is_numeric($execution_time))
256         {
257         $execution_time = round($execution_time / 60 , 3);
258         }
259       $reporter->paintUpdateEnd($execution_time);
260       return true;
261       }
262
263      echo "error: updateSVN: empty svnroot\n";
264      return false;
265    }
266
267
268  /**
269     *    perform an update of a revision in the svn
270     *    @return the time execution of the svn update
271     *    @param object $reporter
272     *    @param string $svnroot
273     *    @access private
274     */
275    function __performSvnUpdate($reporter,$svnroot,$type){
276      $time_start = (float) array_sum(explode(' ',microtime()));
277      $grepCmd = 'grep';
278      global $isWindows;
279      if ($isWindows)
280        {
281        $grepCmd = 'findstr';
282        }
283      $raw_output = $this->__performSvnCommand(`svn info "$svnroot" 2>&1 | $grepCmd Revision`);
284      // We catch the current revision of the repository
285      $currentRevision = str_replace('Revision: ','',$raw_output[0]);
286      $raw_output = $this->__performSvnCommand(`svn update "$svnroot" 2>&1 | $grepCmd revision`);
287      if(strpos($raw_output[0],'revision') === false)
288        {
289        $execution_time  = "Svn Error:\nsvn update did not return the right standard output.\n";
290        $execution_time .= "svn update did not work on your repository\n";
291        echo "error: __performSvnUpdate: svn update failed\n";
292        return $execution_time;
293        }
294      if(strpos($raw_output[0],'At revision') !== false)
295        {
296        if(!strcmp($type,'Continuous'))
297          {
298          echo "__performSvnUpdate: type=[$type], returning false\n";
299          return false;
300          }
301        $time_end = (float) array_sum(explode(' ',microtime()));
302        $execution_time = $time_end - $time_start;
303        echo "Old revision of repository is: $currentRevision\nCurrent revision of repository is: $currentRevision\n";
304        echo "Project is up to date\n";
305        return $execution_time;
306        }
307      $newRevision = str_replace('Updated to revision ','',$raw_output[0]);
308      $newRevision = strtok($newRevision,'.');
309      $raw_output = `svn log "$svnroot" -r $currentRevision:$newRevision -v --xml 2>&1`;
310      $reporter->paintUpdateFile($raw_output);
311      $time_end = (float) array_sum(explode(' ',microtime()));
312      $execution_time = $time_end - $time_start;
313      echo "Your Repository has just been updated from revision $currentRevision to revision $newRevision\n";
314      echo "\tRepository concerned: [$svnroot]\n";
315      echo "\tUse SVN repository type\n";
316      echo "Project is up to date\n";
317      return $execution_time;
318    }
319
320
321  /**
322     * perform a command line
323     * @return an array of the output result of the commandline
324     * @param command $commandline
325     */
326    function __performSvnCommand($commandline)
327    {
328      return explode("\n", $commandline);
329    }
330
331
332 /**
333    * configure the database for the test by droping the old
334    * test database and creating a new one
335    * @param object $reporter
336    * @param array $db
337    */
338  function configure($reporter, $logfilename)
339   {
340      if(!$this->database)
341       {
342       echo "Please, set the database to the test manager before configure the test\n";
343       return false;
344       }
345     $reporter->paintConfigureStart();
346     $time_start = (float) array_sum(explode(' ',microtime()));
347     $result = $this->_uninstalldb4test($this->database['host'],
348                                        $this->database['port'],
349                                        $this->database['login'],
350                                        $this->database['pwd'],
351                                        $this->database['name'],
352                                        $this->database['type']);
353    $time_end = (float) array_sum(explode(' ',microtime()));
354    $execution_time = $time_end - $time_start;
355    $time_start = $time_end;
356    $reporter->paintConfigureUninstallResult($result);
357    $result = $this->_connectToDb($this->database['host'],
358                                  $this->database['port'],
359                                  $this->database['login'],
360                                  $this->database['pwd'],
361                                  $this->database['name'],
362                                  $this->database['type']);
363    $reporter->paintConfigureConnection($result);
364
365    if (file_exists($logfilename))
366      {
367      // delete the log file -- result is success/failure
368      $result = cdash_testsuite_unlink($logfilename);
369      }
370    else
371      {
372      // file is already not there -- equivalent to successfully deleting it
373      $result = true;
374      }
375    $reporter->paintConfigureDeleteLogResult($result, $logfilename);
376
377    $result = $this->_installdb4test($this->database['host'],
378                                     $this->database['port'],
379                                     $this->database['login'],
380                                     $this->database['pwd'],
381                                     $this->database['name'],
382                                     $this->database['type']);
383    $time_end = (float) array_sum(explode(' ',microtime()));
384    $execution_time += ($time_end - $time_start);
385    $execution_time = round($execution_time / 60 , 3);
386    $reporter->paintConfigureInstallResult($result);
387    $result = $this->_connectToDb($this->database['host'],
388                                  $this->database['port'],
389                                  $this->database['login'],
390                                  $this->database['pwd'],
391                                  $this->database['name'],
392                                  $this->database['type']);
393    $reporter->paintConfigureConnection($result);
394    $reporter->paintConfigureEnd($execution_time);
395    return $result;
396   }
397
398
399  /**
400   * Check the log file of the application testing
401   * @return false if there is no log file or no error into the log file
402   *         true if it caught some errors from the log file
403   * @param object $application
404   * @param object $reporter
405   */
406  function getErrorFromServer($filename, $reporter)
407    {
408    if(!file_exists($filename))
409      {
410      return false;
411      }
412    $content  = file_get_contents($filename);
413    if(empty($content))
414      {
415      return false;
416      }
417    // For midas cake: the log time looks like this: if it is not
418    // a cake midas application that you're testing, comment the following line
419    // and implement your own regex
420    //$regex = "([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})";
421
422    // the regex to catch the date for cdash: model: [2009-02-25T18:24:56]
423    $regex = "([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})T([0-9]{2}):([0-9]{2}):([0-9]{2})\]";
424    $fp = fopen($filename,'r');
425    $content = fread($fp,filesize($filename));
426    fclose($fp);
427    unset($fp);
428    $output = split($regex,$content);
429    foreach($output as $message)
430      {
431      $reporter->paintServerFail($message);
432      }
433    return true;
434    }
435
436  /**
437     *    Send via a curl to the CDash server the xml reports
438     *    @return true on success / false on failure
439     */
440    function sendToCdash($reporter,$directory){
441      if(!$this->_urlToCdash)
442        {
443        echo "please set the url to the cdash server before calling sendToCdash method\n";
444        return false;
445        }
446      $reporter->close();
447      $msg = "Submit files (using http)\n\tUsing HTTP submit method\n\t";
448      $msg .= "Drop site: ".$this->_urlToCdash."?project=CDash\n";
449      echo $msg;
450      $filename = $directory.'/Build.xml';
451      $this->__uploadViaCurl($filename);
452      echo "\tUploaded: $filename\n";
453      $filename = $directory.'/Configure.xml';
454      $this->__uploadViaCurl($filename);
455      echo "\tUploaded: $filename\n";
456      $filename = $directory.'/Test.xml';
457      $this->__uploadViaCurl($filename);
458      echo "\tUploaded: $filename\n";
459      $filename = $directory.'/Update.xml';
460      $this->__uploadViaCurl($filename);
461      echo "\tUploaded: $filename\n";
462      echo "\tSubmission successful\n";
463      return true;
464    }
465
466  /**
467     *    Perform a curl to upload the filename to the CDash Server
468     *    @param object $filename
469     */
470    function __uploadViaCurl($filename){
471      $fp = fopen($filename, 'r');
472      $ch = curl_init($this->_urlToCdash.'/submit.php?project=CDash');
473      curl_setopt($ch, CURLOPT_TIMEOUT, 60);
474      curl_setopt($ch, CURLOPT_UPLOAD, 1);
475      curl_setopt($ch, CURLOPT_INFILE, $fp);
476      curl_setopt($ch, CURLOPT_INFILESIZE, filesize($filename));
477      curl_exec($ch);
478      curl_close($ch);
479      fclose($fp);
480      unset($fp);
481    }
482}
483
484
485class HtmlTestManager extends TestManager
486{
487   function runAllTests(&$reporter)
488     {
489     $this->_uninstalldb4test($this->database['host'],
490                              $this->database['port'],
491                              $this->database['login'],
492                              $this->database['pwd'],
493                              $this->database['name'],
494                              $this->database['type']);
495     $this->_installdb4test($this->database['host'],
496                            $this->database['port'],
497                            $this->database['login'],
498                            $this->database['pwd'],
499                            $this->database['name'],
500                            $this->database['type']);
501     parent::runAllTests($reporter);
502     }
503}
504?>
505