MediaWiki REL1_31
DbTestPreviewer.php
Go to the documentation of this file.
1<?php
23 protected $filter; // /< Test name filter callback
24 protected $lb; // /< Database load balancer
25 protected $db; // /< Database connection to the main DB
26 protected $curRun; // /< run ID number for the current run
27 protected $prevRun; // /< run ID number for the previous run, if any
28 protected $results; // /< Result array
29
35 function __construct( $db, $filter = false ) {
36 $this->db = $db;
37 $this->filter = $filter;
38 }
39
44 function start() {
45 if ( !$this->db->tableExists( 'testrun', __METHOD__ )
46 || !$this->db->tableExists( 'testitem', __METHOD__ )
47 ) {
48 print "WARNING> `testrun` table not found in database.\n";
49 $this->prevRun = false;
50 } else {
51 // We'll make comparisons against the previous run later...
52 $this->prevRun = $this->db->selectField( 'testrun', 'MAX(tr_id)' );
53 }
54
55 $this->results = [];
56 }
57
58 function record( $test, ParserTestResult $result ) {
59 $this->results[$test['desc']] = $result->isSuccess() ? 1 : 0;
60 }
61
62 function report() {
63 if ( $this->prevRun ) {
64 // f = fail, p = pass, n = nonexistent
65 // codes show before then after
66 $table = [
67 'fp' => 'previously failing test(s) now PASSING! :)',
68 'pn' => 'previously PASSING test(s) removed o_O',
69 'np' => 'new PASSING test(s) :)',
70
71 'pf' => 'previously passing test(s) now FAILING! :(',
72 'fn' => 'previously FAILING test(s) removed O_o',
73 'nf' => 'new FAILING test(s) :(',
74 'ff' => 'still FAILING test(s) :(',
75 ];
76
77 $prevResults = [];
78
79 $res = $this->db->select( 'testitem', [ 'ti_name', 'ti_success' ],
80 [ 'ti_run' => $this->prevRun ], __METHOD__ );
82
83 foreach ( $res as $row ) {
84 if ( !$filter || $filter( $row->ti_name ) ) {
85 $prevResults[$row->ti_name] = $row->ti_success;
86 }
87 }
88
89 $combined = array_keys( $this->results + $prevResults );
90
91 # Determine breakdown by change type
92 $breakdown = [];
93 foreach ( $combined as $test ) {
94 if ( !isset( $prevResults[$test] ) ) {
95 $before = 'n';
96 } elseif ( $prevResults[$test] == 1 ) {
97 $before = 'p';
98 } else /* if ( $prevResults[$test] == 0 ) */ {
99 $before = 'f';
100 }
101
102 if ( !isset( $this->results[$test] ) ) {
103 $after = 'n';
104 } elseif ( $this->results[$test] == 1 ) {
105 $after = 'p';
106 } else /* if ( $this->results[$test] == 0 ) */ {
107 $after = 'f';
108 }
109
110 $code = $before . $after;
111
112 if ( isset( $table[$code] ) ) {
113 $breakdown[$code][$test] = $this->getTestStatusInfo( $test, $after );
114 }
115 }
116
117 # Write out results
118 foreach ( $table as $code => $label ) {
119 if ( !empty( $breakdown[$code] ) ) {
120 $count = count( $breakdown[$code] );
121 printf( "\n%4d %s\n", $count, $label );
122
123 foreach ( $breakdown[$code] as $differing_test_name => $statusInfo ) {
124 print " * $differing_test_name [$statusInfo]\n";
125 }
126 }
127 }
128 } else {
129 print "No previous test runs to compare against.\n";
130 }
131
132 print "\n";
133 }
134
143 private function getTestStatusInfo( $testname, $after ) {
144 // If we're looking at a test that has just been removed, then say when it first appeared.
145 if ( $after == 'n' ) {
146 $changedRun = $this->db->selectField( 'testitem',
147 'MIN(ti_run)',
148 [ 'ti_name' => $testname ],
149 __METHOD__ );
150 $appear = $this->db->selectRow( 'testrun',
151 [ 'tr_date', 'tr_mw_version' ],
152 [ 'tr_id' => $changedRun ],
153 __METHOD__ );
154
155 return "First recorded appearance: "
156 . date( "d-M-Y H:i:s", strtotime( $appear->tr_date ) )
157 . ", " . $appear->tr_mw_version;
158 }
159
160 // Otherwise, this test has previous recorded results.
161 // See when this test last had a different result to what we're seeing now.
162 $conds = [
163 'ti_name' => $testname,
164 'ti_success' => ( $after == 'f' ? "1" : "0" ) ];
165
166 if ( $this->curRun ) {
167 $conds[] = "ti_run != " . $this->db->addQuotes( $this->curRun );
168 }
169
170 $changedRun = $this->db->selectField( 'testitem', 'MAX(ti_run)', $conds, __METHOD__ );
171
172 // If no record of ever having had a different result.
173 if ( is_null( $changedRun ) ) {
174 if ( $after == "f" ) {
175 return "Has never passed";
176 } else {
177 return "Has never failed";
178 }
179 }
180
181 // Otherwise, we're looking at a test whose status has changed.
182 // (i.e. it used to work, but now doesn't; or used to fail, but is now fixed.)
183 // In this situation, give as much info as we can as to when it changed status.
184 $pre = $this->db->selectRow( 'testrun',
185 [ 'tr_date', 'tr_mw_version' ],
186 [ 'tr_id' => $changedRun ],
187 __METHOD__ );
188 $post = $this->db->selectRow( 'testrun',
189 [ 'tr_date', 'tr_mw_version' ],
190 [ "tr_id > " . $this->db->addQuotes( $changedRun ) ],
191 __METHOD__,
192 [ "LIMIT" => 1, "ORDER BY" => 'tr_id' ]
193 );
194
195 if ( $post ) {
196 $postDate = date( "d-M-Y H:i:s", strtotime( $post->tr_date ) ) . ", {$post->tr_mw_version}";
197 } else {
198 $postDate = 'now';
199 }
200
201 return ( $after == "f" ? "Introduced" : "Fixed" ) . " between "
202 . date( "d-M-Y H:i:s", strtotime( $pre->tr_date ) ) . ", " . $pre->tr_mw_version
203 . " and $postDate";
204 }
205}
record( $test, ParserTestResult $result)
Called after each test.
getTestStatusInfo( $testname, $after)
Returns a string giving information about when a test last had a status change.
report()
Called before finishing the test run.
start()
Set up result recording; insert a record for the run with the date and all that fun stuff.
__construct( $db, $filter=false)
This should be called before the table prefix is changed.
Represent the result of a parser test.
Interface to record parser test results.
$res
Definition database.txt:21
return true to allow those checks to and false if checking is done remove or add to the links of a group of changes in EnhancedChangesList Hook subscribers can return false to omit this line from recentchanges use this to change the tables headers change it to an object instance and return false override the list derivative used the name of the old file when set the default code will be skipped $pre
Definition hooks.txt:1585
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output modifiable & $code
Definition hooks.txt:865
while(( $__line=Maintenance::readconsole()) !==false) print
Definition eval.php:64