]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/PHPUnit/Util/Log/Database.php
Add .gitignore
[Github/sugarcrm.git] / tests / PHPUnit / Util / Log / Database.php
1 <?php
2 /**
3  * PHPUnit
4  *
5  * Copyright (c) 2002-2009, Sebastian Bergmann <sb@sebastian-bergmann.de>.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *
15  *   * Redistributions in binary form must reproduce the above copyright
16  *     notice, this list of conditions and the following disclaimer in
17  *     the documentation and/or other materials provided with the
18  *     distribution.
19  *
20  *   * Neither the name of Sebastian Bergmann nor the names of his
21  *     contributors may be used to endorse or promote products derived
22  *     from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  * @category   Testing
38  * @package    PHPUnit
39  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
40  * @copyright  2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
41  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
42
43  * @link       http://www.phpunit.de/
44  * @since      File available since Release 3.1.0
45  */
46
47 require_once 'PHPUnit/Framework.php';
48 require_once 'PHPUnit/Runner/BaseTestRunner.php';
49 require_once 'PHPUnit/Util/Filter.php';
50
51 PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
52
53 /**
54  * Writes test result and code coverage data to a database.
55  *
56  * @category   Testing
57  * @package    PHPUnit
58  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
59  * @copyright  2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
60  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
61  * @version    Release: 3.3.17
62  * @link       http://www.phpunit.de/
63  * @since      Class available since Release 3.1.0
64  */
65 class PHPUnit_Util_Log_Database implements PHPUnit_Framework_TestListener
66 {
67     /**
68      * @var    PHPUnit_Util_Log_Database
69      */
70     protected static $instance = NULL;
71
72     /**
73      * @var    integer
74      */
75     protected $currentTestId;
76
77     /**
78      * @var    integer
79      */
80     protected $runId;
81
82     /**
83      * @var    integer[]
84      */
85     protected $testSuites = array();
86
87     /**
88      * @var    boolean
89      */
90     protected $currentTestSuccess = TRUE;
91
92     /**
93      * @var    PDO
94      */
95     protected $dbh;
96
97     /**
98      * Constructor.
99      *
100      * @param  PDO     $dbh
101      * @param  integer $revision
102      * @param  string  $information
103      * @throws PDOException
104      * @throws RuntimeException
105      */
106     protected function __construct(PDO $dbh, $revision, $information = '')
107     {
108         $this->dbh = $dbh;
109
110         $stmt = $this->dbh->prepare(
111           'INSERT INTO run
112                        (timestamp, revision, information)
113                  VALUES(:timestamp, :revision, :information);'
114         );
115
116         $timestamp = time();
117
118         $stmt->bindParam(':timestamp', $timestamp, PDO::PARAM_INT);
119         $stmt->bindParam(':revision', $revision, PDO::PARAM_INT);
120         $stmt->bindParam(':information', $information, PDO::PARAM_STR);
121         $stmt->execute();
122
123         $this->runId = $this->dbh->lastInsertId();
124     }
125
126     /**
127      * @param  PDO     $dbh
128      * @param  integer $revision
129      * @param  string  $information
130      * @return PHPUnit_Util_Log_Database
131      * @throws InvalidArgumentException
132      * @throws PDOException
133      * @throws RuntimeException
134      */
135     public static function getInstance(PDO $dbh = NULL, $revision = '', $information = '')
136     {
137         if ($dbh === NULL) {
138             if (self::$instance != NULL) {
139                 return self::$instance;
140             } else {
141                 return FALSE;
142             }
143         }
144
145         if (self::$instance != NULL) {
146             throw new RuntimeException;
147         }
148
149         if (empty($revision)) {
150             throw new InvalidArgumentException;
151         }
152
153         self::$instance = new PHPUnit_Util_Log_Database(
154           $dbh, $revision, $information
155         );
156
157         return self::$instance;
158     }
159
160     /**
161      * Returns the ID of the current test.
162      *
163      * @return integer
164      */
165     public function getCurrentTestId()
166     {
167         return $this->currentTestId;
168     }
169
170     /**
171      * Returns the ID of this test run.
172      *
173      * @return integer
174      */
175     public function getRunId()
176     {
177         return $this->runId;
178     }
179
180     /**
181      * An error occurred.
182      *
183      * @param  PHPUnit_Framework_Test $test
184      * @param  Exception              $e
185      * @param  float                  $time
186      */
187     public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
188     {
189         $message = PHPUnit_Framework_TestFailure::exceptionToString($e) . "\n" .
190                    PHPUnit_Util_Filter::getFilteredStacktrace($e, FALSE);
191
192         $this->storeResult(
193           PHPUnit_Runner_BaseTestRunner::STATUS_ERROR,
194           $time,
195           $message
196         );
197
198         $this->updateParents(
199           $time, PHPUnit_Runner_BaseTestRunner::STATUS_ERROR
200         );
201
202         $this->currentTestSuccess = FALSE;
203     }
204
205     /**
206      * A failure occurred.
207      *
208      * @param  PHPUnit_Framework_Test                 $test
209      * @param  PHPUnit_Framework_AssertionFailedError $e
210      * @param  float                                  $time
211      */
212     public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
213     {
214         $message = PHPUnit_Framework_TestFailure::exceptionToString($e) . "\n" .
215                    PHPUnit_Util_Filter::getFilteredStacktrace($e, FALSE);
216
217         $this->storeResult(
218           PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE,
219           $time,
220           $message
221         );
222
223         $this->updateParents(
224           $time, PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE
225         );
226
227         $this->currentTestSuccess = FALSE;
228     }
229
230     /**
231      * Incomplete test.
232      *
233      * @param  PHPUnit_Framework_Test $test
234      * @param  Exception              $e
235      * @param  float                  $time
236      */
237     public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time)
238     {
239         $message = PHPUnit_Framework_TestFailure::exceptionToString($e) . "\n" .
240                    PHPUnit_Util_Filter::getFilteredStacktrace($e, FALSE);
241
242         $this->storeResult(
243           PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE,
244           $time,
245           $message
246         );
247
248         $this->currentTestSuccess = FALSE;
249     }
250
251     /**
252      * Skipped test.
253      *
254      * @param  PHPUnit_Framework_Test $test
255      * @param  Exception              $e
256      * @param  float                  $time
257      */
258     public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time)
259     {
260         $message = PHPUnit_Framework_TestFailure::exceptionToString($e) . "\n" .
261                    PHPUnit_Util_Filter::getFilteredStacktrace($e, FALSE);
262
263         $this->storeResult(
264           PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED,
265           $time,
266           $message
267         );
268
269         $this->currentTestSuccess = FALSE;
270     }
271
272     /**
273      * A test suite started.
274      *
275      * @param  PHPUnit_Framework_TestSuite $suite
276      */
277     public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
278     {
279         if (empty($this->testSuites)) {
280             $testSuiteId = $this->insertRootNode($suite->getName());
281         } else {
282             $testSuiteId = $this->insertNode($suite);
283         }
284
285         $this->testSuites[] = array(
286           'id'     => $testSuiteId,
287           'result' => PHPUnit_Runner_BaseTestRunner::STATUS_PASSED
288         );
289     }
290
291     /**
292      * A test suite ended.
293      *
294      * @param  PHPUnit_Framework_TestSuite $suite
295      */
296     public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
297     {
298         array_pop($this->testSuites);
299
300         if (empty($this->testSuites)) {
301             $stmt = $this->dbh->prepare(
302               'UPDATE run
303                   SET completed = 1
304                 WHERE run_id = :runId;'
305             );
306
307             $stmt->bindParam(':runId', $this->runId, PDO::PARAM_INT);
308             $stmt->execute();
309         }
310     }
311
312     /**
313      * A test started.
314      *
315      * @param  PHPUnit_Framework_Test $test
316      */
317     public function startTest(PHPUnit_Framework_Test $test)
318     {
319         $this->insertNode($test);
320         $this->currentTestSuccess = TRUE;
321     }
322
323     /**
324      * A test ended.
325      *
326      * @param  PHPUnit_Framework_Test $test
327      * @param  float                  $time
328      */
329     public function endTest(PHPUnit_Framework_Test $test, $time)
330     {
331         if ($this->currentTestSuccess) {
332             $this->storeResult(
333               PHPUnit_Runner_BaseTestRunner::STATUS_PASSED, $time
334             );
335
336             $this->updateParents($time);
337         }
338     }
339
340     /**
341      * Inserts the root node into the tree.
342      *
343      * @param  string $name
344      * @return integer
345      * @throws PDOException
346      */
347     protected function insertRootNode($name)
348     {
349         $this->dbh->beginTransaction();
350
351         $stmt = $this->dbh->prepare(
352           'INSERT INTO test
353                        (run_id, test_name, node_left, node_right, node_is_leaf)
354                  VALUES(:runId, :testName, 1, 2, 0);'
355         );
356
357         $stmt->bindParam(':runId', $this->runId, PDO::PARAM_INT);
358         $stmt->bindParam(':testName', $name, PDO::PARAM_STR);
359         $stmt->execute();
360
361         $rootId = $this->dbh->lastInsertId();
362
363         $stmt = $this->dbh->prepare(
364           'UPDATE test
365               SET node_root = :root
366             WHERE test_id = :testId;'
367         );
368
369         $stmt->bindParam(':root', $rootId, PDO::PARAM_INT);
370         $stmt->bindParam(':testId', $rootId, PDO::PARAM_INT);
371         $stmt->execute();
372
373         $this->dbh->commit();
374
375         return $rootId;
376     }
377
378     /**
379      * Inserts a node into the tree.
380      *
381      * @param  PHPUnit_Framework_Test $test
382      * @throws PDOException
383      */
384     protected function insertNode(PHPUnit_Framework_Test $test)
385     {
386         $isLeaf = (int)!$test instanceof PHPUnit_Framework_TestSuite;
387
388         $this->dbh->beginTransaction();
389
390         $stmt = $this->dbh->prepare(
391           'SELECT node_right
392              FROM test
393             WHERE test_id = :testId;'
394         );
395
396         $stmt->bindParam(':testId', $this->testSuites[count($this->testSuites)-1]['id'], PDO::PARAM_INT);
397         $stmt->execute();
398
399         $right = (int)$stmt->fetchColumn();
400         unset($stmt);
401
402         $stmt = $this->dbh->prepare(
403           'UPDATE test
404               SET node_left = node_left + 2
405             WHERE node_root = :root
406               AND node_left > :left;'
407         );
408
409         $stmt->bindParam(':root', $this->testSuites[0]['id'], PDO::PARAM_INT);
410         $stmt->bindParam(':left', $right, PDO::PARAM_INT);
411         $stmt->execute();
412
413         $stmt = $this->dbh->prepare(
414           'UPDATE test
415               SET node_right  = node_right + 2
416             WHERE node_root   = :root
417               AND node_right >= :right;'
418         );
419
420         $stmt->bindParam(':root', $this->testSuites[0]['id'], PDO::PARAM_INT);
421         $stmt->bindParam(':right', $right, PDO::PARAM_INT);
422         $stmt->execute();
423
424         $testName = $test->getName();
425         $left     = $right;
426         $right    = $right + 1;
427
428         $stmt = $this->dbh->prepare(
429           'INSERT INTO test
430                        (run_id, test_name, test_result, test_message,
431                         test_execution_time, node_root, node_left, node_right,
432                         node_is_leaf)
433                  VALUES(:runId, :testName, 0, "", 0, :root, :left, :right,
434                         :isLeaf);'
435         );
436
437         $stmt->bindParam(':runId', $this->runId, PDO::PARAM_INT);
438         $stmt->bindParam(':testName', $testName, PDO::PARAM_STR);
439         $stmt->bindParam(':root', $this->testSuites[0]['id'], PDO::PARAM_INT);
440         $stmt->bindParam(':left', $left, PDO::PARAM_INT);
441         $stmt->bindParam(':right', $right, PDO::PARAM_INT);
442         $stmt->bindParam(':isLeaf', $isLeaf, PDO::PARAM_INT);
443         $stmt->execute();
444
445         $this->currentTestId = $this->dbh->lastInsertId();
446         $this->dbh->commit();
447
448         if (!$test instanceof PHPUnit_Framework_TestSuite) {
449             $test->__db_id = $this->currentTestId;
450         }
451
452         return $this->currentTestId;
453     }
454
455     /**
456      * Stores a test result.
457      *
458      * @param  integer $result
459      * @param  float   $time
460      * @param  string  $message
461      * @throws PDOException
462      */
463     protected function storeResult($result = PHPUnit_Runner_BaseTestRunner::STATUS_PASSED, $time = 0, $message = '')
464     {
465         $stmt = $this->dbh->prepare(
466           'UPDATE test
467               SET test_result         = :result,
468                   test_message        = :message,
469                   test_execution_time = :executionTime
470             WHERE test_id             = :testId;'
471         );
472
473         $stmt->bindParam(':result', $result, PDO::PARAM_INT);
474         $stmt->bindParam(':message', $message, PDO::PARAM_STR);
475         $stmt->bindParam(':executionTime', $time);
476         $stmt->bindParam(':testId', $this->currentTestId, PDO::PARAM_INT);
477         $stmt->execute();
478     }
479
480     /**
481      * @param  float   $time
482      * @param  integer $result
483      * @throws PDOException
484      */
485     protected function updateParents($time, $result = NULL)
486     {
487         $stmtUpdateResultAndTime = $this->dbh->prepare(
488           'UPDATE test
489               SET test_result         = :result,
490                   test_execution_time = test_execution_time + :time
491             WHERE test_id             = :testSuiteId;'
492         );
493
494         $stmtUpdateTime = $this->dbh->prepare(
495           'UPDATE test
496               SET test_execution_time = test_execution_time + :time
497             WHERE test_id             = :testSuiteId;'
498         );
499
500         foreach ($this->testSuites as &$testSuite) {
501             if ($result > $testSuite['result']) {
502                 $stmtUpdateResultAndTime->bindParam(':result', $result, PDO::PARAM_INT);
503                 $stmtUpdateResultAndTime->bindParam(':testSuiteId', $testSuite['id'], PDO::PARAM_INT);
504                 $stmtUpdateResultAndTime->bindParam(':time', $time);
505                 $stmtUpdateResultAndTime->execute();
506
507                 $testSuite['result'] = $result;
508             } else {
509                 $stmtUpdateTime->bindParam(':testSuiteId', $testSuite['id'], PDO::PARAM_INT);
510                 $stmtUpdateTime->bindParam(':time', $time);
511                 $stmtUpdateTime->execute();
512             }
513         }
514     }
515 }
516 ?>