Bug 8824: check read permission when exporting
[lhc/web/wiklou.git] / Test.php
1 <?php
2
3 /*
4
5 =head1 NAME
6
7 Test.php - L<Test::More> for PHP
8
9 =head1 SYNOPSIS
10
11 require 'Test.php';
12
13 plan( $num ); # plan $num tests
14 # or
15 plan( 'no_plan' ); # We don't know how many
16 # or
17 plan( 'skip_all' ); # Skip all tests
18 # or
19 plan( 'skip_all', $reason ); # Skip all tests with a reason
20
21 diag( 'message in test output' ) # Trailing \n not required
22
23 # $test_name is always optional and should be a short description of
24 # the test, e.g. "some_function() returns an integer"
25
26 # Various ways to say "ok"
27 ok( $got == $expected, $test_name );
28
29 # Compare with == and !=
30 is( $got, $expected, $test_name );
31 isnt( $got, $expected, $test_name );
32
33 # Run a preg match on some data
34 like( $got, $regex, $test_name );
35 unlike( $got, $regex, $test_name );
36
37 # Compare something with a given comparison operator
38 cmp_ok( $got, '==', $expected, $test_name );
39 # Compare something with a comparison function (should return bool)
40 cmp_ok( $got, $func, $expected, $test_name );
41
42 # Recursively check datastructures for equalness
43 is_deeply( $got, $expected, $test_name );
44
45 # Always pass or fail a test under an optional name
46 pass( $test_name );
47 fail( $test_name );
48
49 =head1 DESCRIPTION
50
51 F<Test.php> is an implementation of Perl's L<Test::More> and Pugs's B<Test> for
52 PHP. Like those two modules it produces TAP output (see L<TAP>) which
53 can then be gathered, formatted and summarized by a program that
54 understands TAP such as L<prove(1)>.
55
56 =cut
57
58 */
59
60 register_shutdown_function('test_ends');
61
62 $Test = array(
63 'run' => 0,
64 'failed' => 0,
65 'badpass' => 0,
66 'planned' => null
67 );
68
69 function plan( $plan, $why = '' )
70 {
71 global $Test;
72
73 $Test['planned'] = true;
74
75 switch ( $plan )
76 {
77 case 'no_plan':
78 $Test['planned'] = false;
79 break;
80 case 'skip_all';
81 printf( "1..0%s\n", $why ? " # Skip $why" : '' );
82 exit;
83 default:
84 printf( "1..%d\n", $plan );
85 break;
86 }
87 }
88
89 function pass( $desc = '' )
90 {
91 return proclaim(true, $desc);
92 }
93
94 function fail( $desc = '' )
95 {
96 return proclaim( false, $desc );
97 }
98
99 function ok( $cond, $desc = '' ) {
100 return proclaim( $cond, $desc );
101 }
102
103 function is( $got, $expected, $desc = '' ) {
104 $pass = $got == $expected;
105 return proclaim( $pass, $desc, /* todo */ false, $got, $expected );
106 }
107
108 function isnt( $got, $expected, $desc = '' ) {
109 $pass = $got != $expected;
110 return proclaim( $pass, $desc, /* todo */ false, $got, $expected, /* negated */ true );
111 }
112
113 function like( $got, $expected, $desc = '' ) {
114 $pass = preg_match( $expected, $got );
115 return proclaim( $pass, $desc, /* todo */ false, $got, $expected );
116 }
117
118 function unlike( $got, $expected, $desc = '' ) {
119 $pass = ! preg_match( $expected, $got );
120 return proclaim( $pass, $desc, /* todo */ false, $got, $expected, /* negated */ true );
121 }
122
123 function cmp_ok($got, $op, $expected, $desc = '')
124 {
125 $pass = null;
126
127 /* See http://www.php.net/manual/en/language.operators.comparison.php */
128 switch ($op)
129 {
130 case '==':
131 $pass = $got == $expected;
132 break;
133 case '===':
134 $pass = $got === $expected;
135 break;
136 case '!=':
137 case '<>':
138 $pass = $got != $expected;
139 break;
140 case '!==':
141 $pass = $got !== $expected;
142 break;
143 case '<':
144 $pass = $got < $expected;
145 break;
146 case '>':
147 $pass = $got > $expected;
148 break;
149 case '<=':
150 $pass = $got <= $expected;
151 break;
152 case '>=':
153 $pass = $got >= $expected;
154 break;
155 default:
156 if ( function_exists( $op ) ) {
157 $pass = $op( $got, $expected );
158 } else {
159 die("No such operator or function $op\n");
160 }
161 }
162
163 return proclaim( $pass, $desc, /* todo */ false, $got, "$op $expected" );
164 }
165
166 function diag($message)
167 {
168 if (is_array($message))
169 {
170 $message = implode("\n", $message);
171 }
172
173 $messages = explode("\n", $message);
174
175 foreach ($messages as $msg)
176 {
177 echo "# $msg\n";
178 }
179 }
180
181 function include_ok( $file, $desc = '' )
182 {
183 $pass = include $file;
184 return proclaim( $pass, $desc == '' ? "include $file" : $desc );
185 }
186
187 function require_ok( $file, $desc = '' )
188 {
189 $pass = require $file;
190 return proclaim( $pass, $desc == '' ? "require $file" : $desc );
191 }
192
193 function is_deeply( $got, $expected, $desc = '' )
194 {
195 // hack
196 $s_got = serialize( $got );
197 $s_exp = serialize( $expected );
198
199 $pass = $s_got == $s_exp;
200
201 proclaim( $pass, $desc, /* todo */ false, $got, $expected );
202 }
203
204 function isa_ok( $obj, $expected, $desc = '' ) {
205 $name = get_class( $obj );
206 $pass = $name == $expected;
207 proclaim( $pass, $desc, /* todo */ false, $name, $expected );
208 }
209
210 function proclaim(
211 $cond, // bool
212 $desc = '',
213 $todo = false,
214 $got = null,
215 $expected = null,
216 $negate = false ) {
217
218 global $Test;
219
220 $Test['run'] += 1;
221
222 # TODO: force_todo
223
224 # Everything after the first # is special, so escape user-supplied messages
225 $desc = str_replace( '#', '\\#', $desc );
226 $desc = str_replace( "\n", '\\n', $desc );
227
228 $ok = $cond ? "ok" : "not ok";
229 $directive = $todo === false ? '' : '# TODO aoeu';
230
231 printf( "%s %d %s%s\n", $ok, $Test['run'], $desc, $directive );
232
233 if ( ! $cond ) {
234 report_failure( $desc, $got, $expected, $negate, $todo );
235 }
236
237 return $cond;
238 }
239
240 function report_failure( $desc, $got, $expected, $negate, $todo ) {
241 # Every public function in this file proclaim which then calls
242 # this function, so our culprit is the third item in the stack
243 $caller = debug_backtrace();
244 $call = $caller['2'];
245
246 diag(
247 sprintf( " Failed%stest '%s'\n in %s at line %d\n got: %s\n expected: %s",
248 $todo ? ' TODO ' : ' ',
249 $desc,
250 $call['file'],
251 $call['line'],
252 $got,
253 $expected
254 )
255 );
256 }
257
258 function test_ends ()
259 {
260 global $Test;
261
262 if ( $Test['planned'] === false ) {
263 printf( "1..%d\n", $Test['run'] );
264 }
265 }
266
267 /*
268
269 =head1 TODO
270
271 =over
272
273 =item * Fully document this file
274
275 =item *
276
277 Add TODO support, maybe via C<ok(0, "foo # TODO fix this")>
278 C<ok(1, "foo", array( 'todo' => 'fix this'))>.
279
280 =back
281
282 =head1 SEE ALSO
283
284 =over
285
286 =item L<TAP> - The TAP protocol
287
288 =item L<Test::More>
289
290 =item Pugs's Test.pm
291
292 =back
293
294 =head1 AUTHOR
295
296 Ævar Arnfjörð Bjarmason <avarab@gmail.com>
297
298 =head1 LICENSING
299
300 This program is free software; you can redistribute it and/or modify it
301 under the same terms as Perl itself.
302
303 =cut
304
305 */
306
307 ?>