Merge "mediawiki.mixins.rotation: Remove unnecessary @-o-keyframes"
[lhc/web/wiklou.git] / tests / phpunit / includes / api / ApiResultTest.php
1 <?php
2
3 /**
4 * @covers ApiResult
5 * @group API
6 */
7 class ApiResultTest extends MediaWikiTestCase {
8
9 /**
10 * @covers ApiResult
11 */
12 public function testStaticDataMethods() {
13 $arr = array();
14
15 ApiResult::setValue( $arr, 'setValue', '1' );
16
17 ApiResult::setValue( $arr, null, 'unnamed 1' );
18 ApiResult::setValue( $arr, null, 'unnamed 2' );
19
20 ApiResult::setValue( $arr, 'deleteValue', '2' );
21 ApiResult::unsetValue( $arr, 'deleteValue' );
22
23 ApiResult::setContentValue( $arr, 'setContentValue', '3' );
24
25 $this->assertSame( array(
26 'setValue' => '1',
27 'unnamed 1',
28 'unnamed 2',
29 ApiResult::META_CONTENT => 'setContentValue',
30 'setContentValue' => '3',
31 ), $arr );
32
33 try {
34 ApiResult::setValue( $arr, 'setValue', '99' );
35 $this->fail( 'Expected exception not thrown' );
36 } catch ( RuntimeException $ex ) {
37 $this->assertSame(
38 'Attempting to add element setValue=99, existing value is 1',
39 $ex->getMessage(),
40 'Expected exception'
41 );
42 }
43
44 try {
45 ApiResult::setContentValue( $arr, 'setContentValue2', '99' );
46 $this->fail( 'Expected exception not thrown' );
47 } catch ( RuntimeException $ex ) {
48 $this->assertSame(
49 'Attempting to set content element as setContentValue2 when setContentValue ' .
50 'is already set as the content element',
51 $ex->getMessage(),
52 'Expected exception'
53 );
54 }
55
56 ApiResult::setValue( $arr, 'setValue', '99', ApiResult::OVERRIDE );
57 $this->assertSame( '99', $arr['setValue'] );
58
59 ApiResult::setContentValue( $arr, 'setContentValue2', '99', ApiResult::OVERRIDE );
60 $this->assertSame( 'setContentValue2', $arr[ApiResult::META_CONTENT] );
61
62 $arr = array( 'foo' => 1, 'bar' => 1 );
63 ApiResult::setValue( $arr, 'top', '2', ApiResult::ADD_ON_TOP );
64 ApiResult::setValue( $arr, null, '2', ApiResult::ADD_ON_TOP );
65 ApiResult::setValue( $arr, 'bottom', '2' );
66 ApiResult::setValue( $arr, 'foo', '2', ApiResult::OVERRIDE );
67 ApiResult::setValue( $arr, 'bar', '2', ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP );
68 $this->assertSame( array( 0, 'top', 'foo', 'bar', 'bottom' ), array_keys( $arr ) );
69
70 $arr = array();
71 ApiResult::setValue( $arr, 'sub', array( 'foo' => 1 ) );
72 ApiResult::setValue( $arr, 'sub', array( 'bar' => 1 ) );
73 $this->assertSame( array( 'sub' => array( 'foo' => 1, 'bar' => 1 ) ), $arr );
74
75 try {
76 ApiResult::setValue( $arr, 'sub', array( 'foo' => 2, 'baz' => 2 ) );
77 $this->fail( 'Expected exception not thrown' );
78 } catch ( RuntimeException $ex ) {
79 $this->assertSame(
80 'Conflicting keys (foo) when attempting to merge element sub',
81 $ex->getMessage(),
82 'Expected exception'
83 );
84 }
85
86 $arr = array();
87 $title = Title::newFromText( "MediaWiki:Foobar" );
88 $obj = new stdClass;
89 $obj->foo = 1;
90 $obj->bar = 2;
91 ApiResult::setValue( $arr, 'title', $title );
92 ApiResult::setValue( $arr, 'obj', $obj );
93 $this->assertSame( array(
94 'title' => (string)$title,
95 'obj' => array( 'foo' => 1, 'bar' => 2, ApiResult::META_TYPE => 'assoc' ),
96 ), $arr );
97
98 $fh = tmpfile();
99 try {
100 ApiResult::setValue( $arr, 'file', $fh );
101 $this->fail( 'Expected exception not thrown' );
102 } catch ( InvalidArgumentException $ex ) {
103 $this->assertSame(
104 'Cannot add resource(stream) to ApiResult',
105 $ex->getMessage(),
106 'Expected exception'
107 );
108 }
109 try {
110 ApiResult::setValue( $arr, null, $fh );
111 $this->fail( 'Expected exception not thrown' );
112 } catch ( InvalidArgumentException $ex ) {
113 $this->assertSame(
114 'Cannot add resource(stream) to ApiResult',
115 $ex->getMessage(),
116 'Expected exception'
117 );
118 }
119 try {
120 $obj->file = $fh;
121 ApiResult::setValue( $arr, 'sub', $obj );
122 $this->fail( 'Expected exception not thrown' );
123 } catch ( InvalidArgumentException $ex ) {
124 $this->assertSame(
125 'Cannot add resource(stream) to ApiResult',
126 $ex->getMessage(),
127 'Expected exception'
128 );
129 }
130 try {
131 $obj->file = $fh;
132 ApiResult::setValue( $arr, null, $obj );
133 $this->fail( 'Expected exception not thrown' );
134 } catch ( InvalidArgumentException $ex ) {
135 $this->assertSame(
136 'Cannot add resource(stream) to ApiResult',
137 $ex->getMessage(),
138 'Expected exception'
139 );
140 }
141 fclose( $fh );
142
143 try {
144 ApiResult::setValue( $arr, 'inf', INF );
145 $this->fail( 'Expected exception not thrown' );
146 } catch ( InvalidArgumentException $ex ) {
147 $this->assertSame(
148 'Cannot add non-finite floats to ApiResult',
149 $ex->getMessage(),
150 'Expected exception'
151 );
152 }
153 try {
154 ApiResult::setValue( $arr, null, INF );
155 $this->fail( 'Expected exception not thrown' );
156 } catch ( InvalidArgumentException $ex ) {
157 $this->assertSame(
158 'Cannot add non-finite floats to ApiResult',
159 $ex->getMessage(),
160 'Expected exception'
161 );
162 }
163 try {
164 ApiResult::setValue( $arr, 'nan', NAN );
165 $this->fail( 'Expected exception not thrown' );
166 } catch ( InvalidArgumentException $ex ) {
167 $this->assertSame(
168 'Cannot add non-finite floats to ApiResult',
169 $ex->getMessage(),
170 'Expected exception'
171 );
172 }
173 try {
174 ApiResult::setValue( $arr, null, NAN );
175 $this->fail( 'Expected exception not thrown' );
176 } catch ( InvalidArgumentException $ex ) {
177 $this->assertSame(
178 'Cannot add non-finite floats to ApiResult',
179 $ex->getMessage(),
180 'Expected exception'
181 );
182 }
183
184 ApiResult::setValue( $arr, null, NAN, ApiResult::NO_VALIDATE );
185
186 try {
187 ApiResult::setValue( $arr, null, NAN, ApiResult::NO_SIZE_CHECK );
188 $this->fail( 'Expected exception not thrown' );
189 } catch ( InvalidArgumentException $ex ) {
190 $this->assertSame(
191 'Cannot add non-finite floats to ApiResult',
192 $ex->getMessage(),
193 'Expected exception'
194 );
195 }
196
197 $arr = array();
198 $result2 = new ApiResult( 8388608 );
199 $result2->addValue( null, 'foo', 'bar' );
200 ApiResult::setValue( $arr, 'baz', $result2 );
201 $this->assertSame( array(
202 'baz' => array(
203 ApiResult::META_TYPE => 'assoc',
204 'foo' => 'bar',
205 )
206 ), $arr );
207
208 $arr = array();
209 ApiResult::setValue( $arr, 'foo', "foo\x80bar" );
210 ApiResult::setValue( $arr, 'bar', "a\xcc\x81" );
211 ApiResult::setValue( $arr, 'baz', 74 );
212 ApiResult::setValue( $arr, null, "foo\x80bar" );
213 ApiResult::setValue( $arr, null, "a\xcc\x81" );
214 $this->assertSame( array(
215 'foo' => "foo\xef\xbf\xbdbar",
216 'bar' => "\xc3\xa1",
217 'baz' => 74,
218 0 => "foo\xef\xbf\xbdbar",
219 1 => "\xc3\xa1",
220 ), $arr );
221
222 $obj = new stdClass;
223 $obj->{'1'} = 'one';
224 $arr = array();
225 ApiResult::setValue( $arr, 'foo', $obj );
226 $this->assertSame( array(
227 'foo' => array(
228 1 => 'one',
229 ApiResult::META_TYPE => 'assoc',
230 )
231 ), $arr );
232 }
233
234 /**
235 * @covers ApiResult
236 */
237 public function testInstanceDataMethods() {
238 $result = new ApiResult( 8388608 );
239
240 $result->addValue( null, 'setValue', '1' );
241
242 $result->addValue( null, null, 'unnamed 1' );
243 $result->addValue( null, null, 'unnamed 2' );
244
245 $result->addValue( null, 'deleteValue', '2' );
246 $result->removeValue( null, 'deleteValue' );
247
248 $result->addValue( array( 'a', 'b' ), 'deleteValue', '3' );
249 $result->removeValue( array( 'a', 'b', 'deleteValue' ), null, '3' );
250
251 $result->addContentValue( null, 'setContentValue', '3' );
252
253 $this->assertSame( array(
254 'setValue' => '1',
255 'unnamed 1',
256 'unnamed 2',
257 'a' => array( 'b' => array() ),
258 'setContentValue' => '3',
259 ApiResult::META_TYPE => 'assoc',
260 ApiResult::META_CONTENT => 'setContentValue',
261 ), $result->getResultData() );
262 $this->assertSame( 20, $result->getSize() );
263
264 try {
265 $result->addValue( null, 'setValue', '99' );
266 $this->fail( 'Expected exception not thrown' );
267 } catch ( RuntimeException $ex ) {
268 $this->assertSame(
269 'Attempting to add element setValue=99, existing value is 1',
270 $ex->getMessage(),
271 'Expected exception'
272 );
273 }
274
275 try {
276 $result->addContentValue( null, 'setContentValue2', '99' );
277 $this->fail( 'Expected exception not thrown' );
278 } catch ( RuntimeException $ex ) {
279 $this->assertSame(
280 'Attempting to set content element as setContentValue2 when setContentValue ' .
281 'is already set as the content element',
282 $ex->getMessage(),
283 'Expected exception'
284 );
285 }
286
287 $result->addValue( null, 'setValue', '99', ApiResult::OVERRIDE );
288 $this->assertSame( '99', $result->getResultData( array( 'setValue' ) ) );
289
290 $result->addContentValue( null, 'setContentValue2', '99', ApiResult::OVERRIDE );
291 $this->assertSame( 'setContentValue2',
292 $result->getResultData( array( ApiResult::META_CONTENT ) ) );
293
294 $result->reset();
295 $this->assertSame( array(
296 ApiResult::META_TYPE => 'assoc',
297 ), $result->getResultData() );
298 $this->assertSame( 0, $result->getSize() );
299
300 $result->addValue( null, 'foo', 1 );
301 $result->addValue( null, 'bar', 1 );
302 $result->addValue( null, 'top', '2', ApiResult::ADD_ON_TOP );
303 $result->addValue( null, null, '2', ApiResult::ADD_ON_TOP );
304 $result->addValue( null, 'bottom', '2' );
305 $result->addValue( null, 'foo', '2', ApiResult::OVERRIDE );
306 $result->addValue( null, 'bar', '2', ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP );
307 $this->assertSame( array( 0, 'top', 'foo', 'bar', 'bottom', ApiResult::META_TYPE ),
308 array_keys( $result->getResultData() ) );
309
310 $result->reset();
311 $result->addValue( null, 'foo', array( 'bar' => 1 ) );
312 $result->addValue( array( 'foo', 'top' ), 'x', 2, ApiResult::ADD_ON_TOP );
313 $result->addValue( array( 'foo', 'bottom' ), 'x', 2 );
314 $this->assertSame( array( 'top', 'bar', 'bottom' ),
315 array_keys( $result->getResultData( array( 'foo' ) ) ) );
316
317 $result->reset();
318 $result->addValue( null, 'sub', array( 'foo' => 1 ) );
319 $result->addValue( null, 'sub', array( 'bar' => 1 ) );
320 $this->assertSame( array(
321 'sub' => array( 'foo' => 1, 'bar' => 1 ),
322 ApiResult::META_TYPE => 'assoc',
323 ), $result->getResultData() );
324
325 try {
326 $result->addValue( null, 'sub', array( 'foo' => 2, 'baz' => 2 ) );
327 $this->fail( 'Expected exception not thrown' );
328 } catch ( RuntimeException $ex ) {
329 $this->assertSame(
330 'Conflicting keys (foo) when attempting to merge element sub',
331 $ex->getMessage(),
332 'Expected exception'
333 );
334 }
335
336 $result->reset();
337 $title = Title::newFromText( "MediaWiki:Foobar" );
338 $obj = new stdClass;
339 $obj->foo = 1;
340 $obj->bar = 2;
341 $result->addValue( null, 'title', $title );
342 $result->addValue( null, 'obj', $obj );
343 $this->assertSame( array(
344 'title' => (string)$title,
345 'obj' => array( 'foo' => 1, 'bar' => 2, ApiResult::META_TYPE => 'assoc' ),
346 ApiResult::META_TYPE => 'assoc',
347 ), $result->getResultData() );
348
349 $fh = tmpfile();
350 try {
351 $result->addValue( null, 'file', $fh );
352 $this->fail( 'Expected exception not thrown' );
353 } catch ( InvalidArgumentException $ex ) {
354 $this->assertSame(
355 'Cannot add resource(stream) to ApiResult',
356 $ex->getMessage(),
357 'Expected exception'
358 );
359 }
360 try {
361 $result->addValue( null, null, $fh );
362 $this->fail( 'Expected exception not thrown' );
363 } catch ( InvalidArgumentException $ex ) {
364 $this->assertSame(
365 'Cannot add resource(stream) to ApiResult',
366 $ex->getMessage(),
367 'Expected exception'
368 );
369 }
370 try {
371 $obj->file = $fh;
372 $result->addValue( null, 'sub', $obj );
373 $this->fail( 'Expected exception not thrown' );
374 } catch ( InvalidArgumentException $ex ) {
375 $this->assertSame(
376 'Cannot add resource(stream) to ApiResult',
377 $ex->getMessage(),
378 'Expected exception'
379 );
380 }
381 try {
382 $obj->file = $fh;
383 $result->addValue( null, null, $obj );
384 $this->fail( 'Expected exception not thrown' );
385 } catch ( InvalidArgumentException $ex ) {
386 $this->assertSame(
387 'Cannot add resource(stream) to ApiResult',
388 $ex->getMessage(),
389 'Expected exception'
390 );
391 }
392 fclose( $fh );
393
394 try {
395 $result->addValue( null, 'inf', INF );
396 $this->fail( 'Expected exception not thrown' );
397 } catch ( InvalidArgumentException $ex ) {
398 $this->assertSame(
399 'Cannot add non-finite floats to ApiResult',
400 $ex->getMessage(),
401 'Expected exception'
402 );
403 }
404 try {
405 $result->addValue( null, null, INF );
406 $this->fail( 'Expected exception not thrown' );
407 } catch ( InvalidArgumentException $ex ) {
408 $this->assertSame(
409 'Cannot add non-finite floats to ApiResult',
410 $ex->getMessage(),
411 'Expected exception'
412 );
413 }
414 try {
415 $result->addValue( null, 'nan', NAN );
416 $this->fail( 'Expected exception not thrown' );
417 } catch ( InvalidArgumentException $ex ) {
418 $this->assertSame(
419 'Cannot add non-finite floats to ApiResult',
420 $ex->getMessage(),
421 'Expected exception'
422 );
423 }
424 try {
425 $result->addValue( null, null, NAN );
426 $this->fail( 'Expected exception not thrown' );
427 } catch ( InvalidArgumentException $ex ) {
428 $this->assertSame(
429 'Cannot add non-finite floats to ApiResult',
430 $ex->getMessage(),
431 'Expected exception'
432 );
433 }
434
435 $result->addValue( null, null, NAN, ApiResult::NO_VALIDATE );
436
437 try {
438 $result->addValue( null, null, NAN, ApiResult::NO_SIZE_CHECK );
439 $this->fail( 'Expected exception not thrown' );
440 } catch ( InvalidArgumentException $ex ) {
441 $this->assertSame(
442 'Cannot add non-finite floats to ApiResult',
443 $ex->getMessage(),
444 'Expected exception'
445 );
446 }
447
448 $result->reset();
449 $result->addParsedLimit( 'foo', 12 );
450 $this->assertSame( array(
451 'limits' => array( 'foo' => 12 ),
452 ApiResult::META_TYPE => 'assoc',
453 ), $result->getResultData() );
454 $result->addParsedLimit( 'foo', 13 );
455 $this->assertSame( array(
456 'limits' => array( 'foo' => 13 ),
457 ApiResult::META_TYPE => 'assoc',
458 ), $result->getResultData() );
459 $this->assertSame( null, $result->getResultData( array( 'foo', 'bar', 'baz' ) ) );
460 $this->assertSame( 13, $result->getResultData( array( 'limits', 'foo' ) ) );
461 try {
462 $result->getResultData( array( 'limits', 'foo', 'bar' ) );
463 $this->fail( 'Expected exception not thrown' );
464 } catch ( InvalidArgumentException $ex ) {
465 $this->assertSame(
466 'Path limits.foo is not an array',
467 $ex->getMessage(),
468 'Expected exception'
469 );
470 }
471
472 // Add two values and some metadata, but ensure metadata is not counted
473 $result = new ApiResult( 100 );
474 $obj = array( 'attr' => '12345' );
475 ApiResult::setContentValue( $obj, 'content', '1234567890' );
476 $this->assertTrue( $result->addValue( null, 'foo', $obj ) );
477 $this->assertSame( 15, $result->getSize() );
478
479 $result = new ApiResult( 10 );
480 $formatter = new ApiErrorFormatter( $result, Language::factory( 'en' ), 'none', false );
481 $result->setErrorFormatter( $formatter );
482 $this->assertFalse( $result->addValue( null, 'foo', '12345678901' ) );
483 $this->assertTrue( $result->addValue( null, 'foo', '12345678901', ApiResult::NO_SIZE_CHECK ) );
484 $this->assertSame( 0, $result->getSize() );
485 $result->reset();
486 $this->assertTrue( $result->addValue( null, 'foo', '1234567890' ) );
487 $this->assertFalse( $result->addValue( null, 'foo', '1' ) );
488 $result->removeValue( null, 'foo' );
489 $this->assertTrue( $result->addValue( null, 'foo', '1' ) );
490
491 $result = new ApiResult( 10 );
492 $obj = new ApiResultTestSerializableObject( 'ok' );
493 $obj->foobar = 'foobaz';
494 $this->assertTrue( $result->addValue( null, 'foo', $obj ) );
495 $this->assertSame( 2, $result->getSize() );
496
497 $result = new ApiResult( 8388608 );
498 $result2 = new ApiResult( 8388608 );
499 $result2->addValue( null, 'foo', 'bar' );
500 $result->addValue( null, 'baz', $result2 );
501 $this->assertSame( array(
502 'baz' => array(
503 'foo' => 'bar',
504 ApiResult::META_TYPE => 'assoc',
505 ),
506 ApiResult::META_TYPE => 'assoc',
507 ), $result->getResultData() );
508
509 $result = new ApiResult( 8388608 );
510 $result->addValue( null, 'foo', "foo\x80bar" );
511 $result->addValue( null, 'bar', "a\xcc\x81" );
512 $result->addValue( null, 'baz', 74 );
513 $result->addValue( null, null, "foo\x80bar" );
514 $result->addValue( null, null, "a\xcc\x81" );
515 $this->assertSame( array(
516 'foo' => "foo\xef\xbf\xbdbar",
517 'bar' => "\xc3\xa1",
518 'baz' => 74,
519 0 => "foo\xef\xbf\xbdbar",
520 1 => "\xc3\xa1",
521 ApiResult::META_TYPE => 'assoc',
522 ), $result->getResultData() );
523
524 $result = new ApiResult( 8388608 );
525 $obj = new stdClass;
526 $obj->{'1'} = 'one';
527 $arr = array();
528 $result->addValue( $arr, 'foo', $obj );
529 $this->assertSame( array(
530 'foo' => array(
531 1 => 'one',
532 ApiResult::META_TYPE => 'assoc',
533 ),
534 ApiResult::META_TYPE => 'assoc',
535 ), $result->getResultData() );
536 }
537
538 /**
539 * @covers ApiResult
540 */
541 public function testMetadata() {
542 $arr = array( 'foo' => array( 'bar' => array() ) );
543 $result = new ApiResult( 8388608 );
544 $result->addValue( null, 'foo', array( 'bar' => array() ) );
545
546 $expect = array(
547 'foo' => array(
548 'bar' => array(
549 ApiResult::META_INDEXED_TAG_NAME => 'ritn',
550 ApiResult::META_TYPE => 'default',
551 ),
552 ApiResult::META_INDEXED_TAG_NAME => 'ritn',
553 ApiResult::META_TYPE => 'default',
554 ),
555 ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
556 ApiResult::META_INDEXED_TAG_NAME => 'itn',
557 ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar' ),
558 ApiResult::META_TYPE => 'array',
559 );
560
561 ApiResult::setSubelementsList( $arr, 'foo' );
562 ApiResult::setSubelementsList( $arr, array( 'bar', 'baz' ) );
563 ApiResult::unsetSubelementsList( $arr, 'baz' );
564 ApiResult::setIndexedTagNameRecursive( $arr, 'ritn' );
565 ApiResult::setIndexedTagName( $arr, 'itn' );
566 ApiResult::setPreserveKeysList( $arr, 'foo' );
567 ApiResult::setPreserveKeysList( $arr, array( 'bar', 'baz' ) );
568 ApiResult::unsetPreserveKeysList( $arr, 'baz' );
569 ApiResult::setArrayTypeRecursive( $arr, 'default' );
570 ApiResult::setArrayType( $arr, 'array' );
571 $this->assertSame( $expect, $arr );
572
573 $result->addSubelementsList( null, 'foo' );
574 $result->addSubelementsList( null, array( 'bar', 'baz' ) );
575 $result->removeSubelementsList( null, 'baz' );
576 $result->addIndexedTagNameRecursive( null, 'ritn' );
577 $result->addIndexedTagName( null, 'itn' );
578 $result->addPreserveKeysList( null, 'foo' );
579 $result->addPreserveKeysList( null, array( 'bar', 'baz' ) );
580 $result->removePreserveKeysList( null, 'baz' );
581 $result->addArrayTypeRecursive( null, 'default' );
582 $result->addArrayType( null, 'array' );
583 $this->assertEquals( $expect, $result->getResultData() );
584
585 $arr = array( 'foo' => array( 'bar' => array() ) );
586 $expect = array(
587 'foo' => array(
588 'bar' => array(
589 ApiResult::META_TYPE => 'kvp',
590 ApiResult::META_KVP_KEY_NAME => 'key',
591 ),
592 ApiResult::META_TYPE => 'kvp',
593 ApiResult::META_KVP_KEY_NAME => 'key',
594 ),
595 ApiResult::META_TYPE => 'BCkvp',
596 ApiResult::META_KVP_KEY_NAME => 'bc',
597 );
598 ApiResult::setArrayTypeRecursive( $arr, 'kvp', 'key' );
599 ApiResult::setArrayType( $arr, 'BCkvp', 'bc' );
600 $this->assertSame( $expect, $arr );
601 }
602
603 /**
604 * @covers ApiResult
605 */
606 public function testUtilityFunctions() {
607 $arr = array(
608 'foo' => array(
609 'bar' => array( '_dummy' => 'foobaz' ),
610 'bar2' => (object)array( '_dummy' => 'foobaz' ),
611 'x' => 'ok',
612 '_dummy' => 'foobaz',
613 ),
614 'foo2' => (object)array(
615 'bar' => array( '_dummy' => 'foobaz' ),
616 'bar2' => (object)array( '_dummy' => 'foobaz' ),
617 'x' => 'ok',
618 '_dummy' => 'foobaz',
619 ),
620 ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
621 ApiResult::META_INDEXED_TAG_NAME => 'itn',
622 ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
623 ApiResult::META_TYPE => 'array',
624 '_dummy' => 'foobaz',
625 '_dummy2' => 'foobaz!',
626 );
627 $this->assertEquals( array(
628 'foo' => array(
629 'bar' => array(),
630 'bar2' => (object)array(),
631 'x' => 'ok',
632 ),
633 'foo2' => (object)array(
634 'bar' => array(),
635 'bar2' => (object)array(),
636 'x' => 'ok',
637 ),
638 '_dummy2' => 'foobaz!',
639 ), ApiResult::stripMetadata( $arr ), 'ApiResult::stripMetadata' );
640
641 $metadata = array();
642 $data = ApiResult::stripMetadataNonRecursive( $arr, $metadata );
643 $this->assertEquals( array(
644 'foo' => array(
645 'bar' => array( '_dummy' => 'foobaz' ),
646 'bar2' => (object)array( '_dummy' => 'foobaz' ),
647 'x' => 'ok',
648 '_dummy' => 'foobaz',
649 ),
650 'foo2' => (object)array(
651 'bar' => array( '_dummy' => 'foobaz' ),
652 'bar2' => (object)array( '_dummy' => 'foobaz' ),
653 'x' => 'ok',
654 '_dummy' => 'foobaz',
655 ),
656 '_dummy2' => 'foobaz!',
657 ), $data, 'ApiResult::stripMetadataNonRecursive ($data)' );
658 $this->assertEquals( array(
659 ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
660 ApiResult::META_INDEXED_TAG_NAME => 'itn',
661 ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
662 ApiResult::META_TYPE => 'array',
663 '_dummy' => 'foobaz',
664 ), $metadata, 'ApiResult::stripMetadataNonRecursive ($metadata)' );
665
666 $metadata = null;
667 $data = ApiResult::stripMetadataNonRecursive( (object)$arr, $metadata );
668 $this->assertEquals( (object)array(
669 'foo' => array(
670 'bar' => array( '_dummy' => 'foobaz' ),
671 'bar2' => (object)array( '_dummy' => 'foobaz' ),
672 'x' => 'ok',
673 '_dummy' => 'foobaz',
674 ),
675 'foo2' => (object)array(
676 'bar' => array( '_dummy' => 'foobaz' ),
677 'bar2' => (object)array( '_dummy' => 'foobaz' ),
678 'x' => 'ok',
679 '_dummy' => 'foobaz',
680 ),
681 '_dummy2' => 'foobaz!',
682 ), $data, 'ApiResult::stripMetadataNonRecursive on object ($data)' );
683 $this->assertEquals( array(
684 ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
685 ApiResult::META_INDEXED_TAG_NAME => 'itn',
686 ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
687 ApiResult::META_TYPE => 'array',
688 '_dummy' => 'foobaz',
689 ), $metadata, 'ApiResult::stripMetadataNonRecursive on object ($metadata)' );
690 }
691
692 /**
693 * @covers ApiResult
694 * @dataProvider provideTransformations
695 * @param string $label
696 * @param array $input
697 * @param array $transforms
698 * @param array|Exception $expect
699 */
700 public function testTransformations( $label, $input, $transforms, $expect ) {
701 $result = new ApiResult( false );
702 $result->addValue( null, 'test', $input );
703
704 if ( $expect instanceof Exception ) {
705 try {
706 $output = $result->getResultData( 'test', $transforms );
707 $this->fail( 'Expected exception not thrown', $label );
708 } catch ( Exception $ex ) {
709 $this->assertEquals( $ex, $expect, $label );
710 }
711 } else {
712 $output = $result->getResultData( 'test', $transforms );
713 $this->assertEquals( $expect, $output, $label );
714 }
715 }
716
717 public function provideTransformations() {
718 $kvp = function ( $keyKey, $key, $valKey, $value ) {
719 return array(
720 $keyKey => $key,
721 $valKey => $value,
722 ApiResult::META_PRESERVE_KEYS => array( $keyKey ),
723 ApiResult::META_CONTENT => $valKey,
724 ApiResult::META_TYPE => 'assoc',
725 );
726 };
727 $typeArr = array(
728 'defaultArray' => array( 2 => 'a', 0 => 'b', 1 => 'c' ),
729 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c' ),
730 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c' ),
731 'array' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'array' ),
732 'BCarray' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'BCarray' ),
733 'BCassoc' => array( 'a', 'b', 'c', ApiResult::META_TYPE => 'BCassoc' ),
734 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
735 'kvp' => array( 'x' => 'a', 'y' => 'b', 'z' => array( 'c' ), ApiResult::META_TYPE => 'kvp' ),
736 'BCkvp' => array( 'x' => 'a', 'y' => 'b',
737 ApiResult::META_TYPE => 'BCkvp',
738 ApiResult::META_KVP_KEY_NAME => 'key',
739 ),
740 'kvpmerge' => array( 'x' => 'a', 'y' => array( 'b' ), 'z' => array( 'c' => 'd' ),
741 ApiResult::META_TYPE => 'kvp',
742 ApiResult::META_KVP_MERGE => true,
743 ),
744 'emptyDefault' => array( '_dummy' => 1 ),
745 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
746 '_dummy' => 1,
747 ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
748 );
749 $stripArr = array(
750 'foo' => array(
751 'bar' => array( '_dummy' => 'foobaz' ),
752 'baz' => array(
753 ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
754 ApiResult::META_INDEXED_TAG_NAME => 'itn',
755 ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
756 ApiResult::META_TYPE => 'array',
757 ),
758 'x' => 'ok',
759 '_dummy' => 'foobaz',
760 ),
761 ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
762 ApiResult::META_INDEXED_TAG_NAME => 'itn',
763 ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
764 ApiResult::META_TYPE => 'array',
765 '_dummy' => 'foobaz',
766 '_dummy2' => 'foobaz!',
767 );
768
769 return array(
770 array(
771 'BC: META_BC_BOOLS',
772 array(
773 'BCtrue' => true,
774 'BCfalse' => false,
775 'true' => true,
776 'false' => false,
777 ApiResult::META_BC_BOOLS => array( 0, 'true', 'false' ),
778 ),
779 array( 'BC' => array() ),
780 array(
781 'BCtrue' => '',
782 'true' => true,
783 'false' => false,
784 ApiResult::META_BC_BOOLS => array( 0, 'true', 'false' ),
785 )
786 ),
787 array(
788 'BC: META_BC_SUBELEMENTS',
789 array(
790 'bc' => 'foo',
791 'nobc' => 'bar',
792 ApiResult::META_BC_SUBELEMENTS => array( 'bc' ),
793 ),
794 array( 'BC' => array() ),
795 array(
796 'bc' => array(
797 '*' => 'foo',
798 ApiResult::META_CONTENT => '*',
799 ApiResult::META_TYPE => 'assoc',
800 ),
801 'nobc' => 'bar',
802 ApiResult::META_BC_SUBELEMENTS => array( 'bc' ),
803 ),
804 ),
805 array(
806 'BC: META_CONTENT',
807 array(
808 'content' => '!!!',
809 ApiResult::META_CONTENT => 'content',
810 ),
811 array( 'BC' => array() ),
812 array(
813 '*' => '!!!',
814 ApiResult::META_CONTENT => '*',
815 ),
816 ),
817 array(
818 'BC: BCkvp type',
819 array(
820 'foo' => 'foo value',
821 'bar' => 'bar value',
822 '_baz' => 'baz value',
823 ApiResult::META_TYPE => 'BCkvp',
824 ApiResult::META_KVP_KEY_NAME => 'key',
825 ApiResult::META_PRESERVE_KEYS => array( '_baz' ),
826 ),
827 array( 'BC' => array() ),
828 array(
829 $kvp( 'key', 'foo', '*', 'foo value' ),
830 $kvp( 'key', 'bar', '*', 'bar value' ),
831 $kvp( 'key', '_baz', '*', 'baz value' ),
832 ApiResult::META_TYPE => 'array',
833 ApiResult::META_KVP_KEY_NAME => 'key',
834 ApiResult::META_PRESERVE_KEYS => array( '_baz' ),
835 ),
836 ),
837 array(
838 'BC: BCarray type',
839 array(
840 ApiResult::META_TYPE => 'BCarray',
841 ),
842 array( 'BC' => array() ),
843 array(
844 ApiResult::META_TYPE => 'default',
845 ),
846 ),
847 array(
848 'BC: BCassoc type',
849 array(
850 ApiResult::META_TYPE => 'BCassoc',
851 ),
852 array( 'BC' => array() ),
853 array(
854 ApiResult::META_TYPE => 'default',
855 ),
856 ),
857 array(
858 'BC: BCkvp exception',
859 array(
860 ApiResult::META_TYPE => 'BCkvp',
861 ),
862 array( 'BC' => array() ),
863 new UnexpectedValueException(
864 'Type "BCkvp" used without setting ApiResult::META_KVP_KEY_NAME metadata item'
865 ),
866 ),
867 array(
868 'BC: nobool, no*, nosub',
869 array(
870 'true' => true,
871 'false' => false,
872 'content' => 'content',
873 ApiResult::META_CONTENT => 'content',
874 'bc' => 'foo',
875 ApiResult::META_BC_SUBELEMENTS => array( 'bc' ),
876 'BCarray' => array( ApiResult::META_TYPE => 'BCarray' ),
877 'BCassoc' => array( ApiResult::META_TYPE => 'BCassoc' ),
878 'BCkvp' => array(
879 'foo' => 'foo value',
880 'bar' => 'bar value',
881 '_baz' => 'baz value',
882 ApiResult::META_TYPE => 'BCkvp',
883 ApiResult::META_KVP_KEY_NAME => 'key',
884 ApiResult::META_PRESERVE_KEYS => array( '_baz' ),
885 ),
886 ),
887 array( 'BC' => array( 'nobool', 'no*', 'nosub' ) ),
888 array(
889 'true' => true,
890 'false' => false,
891 'content' => 'content',
892 'bc' => 'foo',
893 'BCarray' => array( ApiResult::META_TYPE => 'default' ),
894 'BCassoc' => array( ApiResult::META_TYPE => 'default' ),
895 'BCkvp' => array(
896 $kvp( 'key', 'foo', '*', 'foo value' ),
897 $kvp( 'key', 'bar', '*', 'bar value' ),
898 $kvp( 'key', '_baz', '*', 'baz value' ),
899 ApiResult::META_TYPE => 'array',
900 ApiResult::META_KVP_KEY_NAME => 'key',
901 ApiResult::META_PRESERVE_KEYS => array( '_baz' ),
902 ),
903 ApiResult::META_CONTENT => 'content',
904 ApiResult::META_BC_SUBELEMENTS => array( 'bc' ),
905 ),
906 ),
907
908 array(
909 'Types: Normal transform',
910 $typeArr,
911 array( 'Types' => array() ),
912 array(
913 'defaultArray' => array( 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ),
914 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
915 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
916 'array' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
917 'BCarray' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
918 'BCassoc' => array( 'a', 'b', 'c', ApiResult::META_TYPE => 'assoc' ),
919 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
920 'kvp' => array( 'x' => 'a', 'y' => 'b',
921 'z' => array( 'c', ApiResult::META_TYPE => 'array' ),
922 ApiResult::META_TYPE => 'assoc'
923 ),
924 'BCkvp' => array( 'x' => 'a', 'y' => 'b',
925 ApiResult::META_TYPE => 'assoc',
926 ApiResult::META_KVP_KEY_NAME => 'key',
927 ),
928 'kvpmerge' => array(
929 'x' => 'a',
930 'y' => array( 'b', ApiResult::META_TYPE => 'array' ),
931 'z' => array( 'c' => 'd', ApiResult::META_TYPE => 'assoc' ),
932 ApiResult::META_TYPE => 'assoc',
933 ApiResult::META_KVP_MERGE => true,
934 ),
935 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ),
936 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
937 '_dummy' => 1,
938 ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
939 ApiResult::META_TYPE => 'assoc',
940 ),
941 ),
942 array(
943 'Types: AssocAsObject',
944 $typeArr,
945 array( 'Types' => array( 'AssocAsObject' => true ) ),
946 (object)array(
947 'defaultArray' => array( 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ),
948 'defaultAssoc' => (object)array( 'x' => 'a',
949 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc'
950 ),
951 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b',
952 0 => 'c', ApiResult::META_TYPE => 'assoc'
953 ),
954 'array' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
955 'BCarray' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
956 'BCassoc' => (object)array( 'a', 'b', 'c', ApiResult::META_TYPE => 'assoc' ),
957 'assoc' => (object)array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
958 'kvp' => (object)array( 'x' => 'a', 'y' => 'b',
959 'z' => array( 'c', ApiResult::META_TYPE => 'array' ),
960 ApiResult::META_TYPE => 'assoc'
961 ),
962 'BCkvp' => (object)array( 'x' => 'a', 'y' => 'b',
963 ApiResult::META_TYPE => 'assoc',
964 ApiResult::META_KVP_KEY_NAME => 'key',
965 ),
966 'kvpmerge' => (object)array(
967 'x' => 'a',
968 'y' => array( 'b', ApiResult::META_TYPE => 'array' ),
969 'z' => (object)array( 'c' => 'd', ApiResult::META_TYPE => 'assoc' ),
970 ApiResult::META_TYPE => 'assoc',
971 ApiResult::META_KVP_MERGE => true,
972 ),
973 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ),
974 'emptyAssoc' => (object)array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
975 '_dummy' => 1,
976 ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
977 ApiResult::META_TYPE => 'assoc',
978 ),
979 ),
980 array(
981 'Types: ArmorKVP',
982 $typeArr,
983 array( 'Types' => array( 'ArmorKVP' => 'name' ) ),
984 array(
985 'defaultArray' => array( 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ),
986 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
987 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
988 'array' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
989 'BCarray' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
990 'BCassoc' => array( 'a', 'b', 'c', ApiResult::META_TYPE => 'assoc' ),
991 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
992 'kvp' => array(
993 $kvp( 'name', 'x', 'value', 'a' ),
994 $kvp( 'name', 'y', 'value', 'b' ),
995 $kvp( 'name', 'z', 'value', array( 'c', ApiResult::META_TYPE => 'array' ) ),
996 ApiResult::META_TYPE => 'array'
997 ),
998 'BCkvp' => array(
999 $kvp( 'key', 'x', 'value', 'a' ),
1000 $kvp( 'key', 'y', 'value', 'b' ),
1001 ApiResult::META_TYPE => 'array',
1002 ApiResult::META_KVP_KEY_NAME => 'key',
1003 ),
1004 'kvpmerge' => array(
1005 $kvp( 'name', 'x', 'value', 'a' ),
1006 $kvp( 'name', 'y', 'value', array( 'b', ApiResult::META_TYPE => 'array' ) ),
1007 array(
1008 'name' => 'z',
1009 'c' => 'd',
1010 ApiResult::META_TYPE => 'assoc',
1011 ApiResult::META_PRESERVE_KEYS => array( 'name' )
1012 ),
1013 ApiResult::META_TYPE => 'array',
1014 ApiResult::META_KVP_MERGE => true,
1015 ),
1016 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ),
1017 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
1018 '_dummy' => 1,
1019 ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
1020 ApiResult::META_TYPE => 'assoc',
1021 ),
1022 ),
1023 array(
1024 'Types: ArmorKVP + BC',
1025 $typeArr,
1026 array( 'BC' => array(), 'Types' => array( 'ArmorKVP' => 'name' ) ),
1027 array(
1028 'defaultArray' => array( 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ),
1029 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
1030 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
1031 'array' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
1032 'BCarray' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
1033 'BCassoc' => array( 'a', 'b', 'c', ApiResult::META_TYPE => 'array' ),
1034 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
1035 'kvp' => array(
1036 $kvp( 'name', 'x', '*', 'a' ),
1037 $kvp( 'name', 'y', '*', 'b' ),
1038 $kvp( 'name', 'z', '*', array( 'c', ApiResult::META_TYPE => 'array' ) ),
1039 ApiResult::META_TYPE => 'array'
1040 ),
1041 'BCkvp' => array(
1042 $kvp( 'key', 'x', '*', 'a' ),
1043 $kvp( 'key', 'y', '*', 'b' ),
1044 ApiResult::META_TYPE => 'array',
1045 ApiResult::META_KVP_KEY_NAME => 'key',
1046 ),
1047 'kvpmerge' => array(
1048 $kvp( 'name', 'x', '*', 'a' ),
1049 $kvp( 'name', 'y', '*', array( 'b', ApiResult::META_TYPE => 'array' ) ),
1050 array(
1051 'name' => 'z',
1052 'c' => 'd',
1053 ApiResult::META_TYPE => 'assoc',
1054 ApiResult::META_PRESERVE_KEYS => array( 'name' ) ),
1055 ApiResult::META_TYPE => 'array',
1056 ApiResult::META_KVP_MERGE => true,
1057 ),
1058 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ),
1059 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
1060 '_dummy' => 1,
1061 ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
1062 ApiResult::META_TYPE => 'assoc',
1063 ),
1064 ),
1065 array(
1066 'Types: ArmorKVP + AssocAsObject',
1067 $typeArr,
1068 array( 'Types' => array( 'ArmorKVP' => 'name', 'AssocAsObject' => true ) ),
1069 (object)array(
1070 'defaultArray' => array( 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ),
1071 'defaultAssoc' => (object)array( 'x' => 'a', 1 => 'b',
1072 0 => 'c', ApiResult::META_TYPE => 'assoc'
1073 ),
1074 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b',
1075 0 => 'c', ApiResult::META_TYPE => 'assoc'
1076 ),
1077 'array' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
1078 'BCarray' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
1079 'BCassoc' => (object)array( 'a', 'b', 'c', ApiResult::META_TYPE => 'assoc' ),
1080 'assoc' => (object)array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
1081 'kvp' => array(
1082 (object)$kvp( 'name', 'x', 'value', 'a' ),
1083 (object)$kvp( 'name', 'y', 'value', 'b' ),
1084 (object)$kvp( 'name', 'z', 'value', array( 'c', ApiResult::META_TYPE => 'array' ) ),
1085 ApiResult::META_TYPE => 'array'
1086 ),
1087 'BCkvp' => array(
1088 (object)$kvp( 'key', 'x', 'value', 'a' ),
1089 (object)$kvp( 'key', 'y', 'value', 'b' ),
1090 ApiResult::META_TYPE => 'array',
1091 ApiResult::META_KVP_KEY_NAME => 'key',
1092 ),
1093 'kvpmerge' => array(
1094 (object)$kvp( 'name', 'x', 'value', 'a' ),
1095 (object)$kvp( 'name', 'y', 'value', array( 'b', ApiResult::META_TYPE => 'array' ) ),
1096 (object)array(
1097 'name' => 'z',
1098 'c' => 'd',
1099 ApiResult::META_TYPE => 'assoc',
1100 ApiResult::META_PRESERVE_KEYS => array( 'name' )
1101 ),
1102 ApiResult::META_TYPE => 'array',
1103 ApiResult::META_KVP_MERGE => true,
1104 ),
1105 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ),
1106 'emptyAssoc' => (object)array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
1107 '_dummy' => 1,
1108 ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
1109 ApiResult::META_TYPE => 'assoc',
1110 ),
1111 ),
1112 array(
1113 'Types: BCkvp exception',
1114 array(
1115 ApiResult::META_TYPE => 'BCkvp',
1116 ),
1117 array( 'Types' => array() ),
1118 new UnexpectedValueException(
1119 'Type "BCkvp" used without setting ApiResult::META_KVP_KEY_NAME metadata item'
1120 ),
1121 ),
1122
1123 array(
1124 'Strip: With ArmorKVP + AssocAsObject transforms',
1125 $typeArr,
1126 array( 'Types' => array( 'ArmorKVP' => 'name', 'AssocAsObject' => true ), 'Strip' => 'all' ),
1127 (object)array(
1128 'defaultArray' => array( 'b', 'c', 'a' ),
1129 'defaultAssoc' => (object)array( 'x' => 'a', 1 => 'b', 0 => 'c' ),
1130 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b', 0 => 'c' ),
1131 'array' => array( 'a', 'c', 'b' ),
1132 'BCarray' => array( 'a', 'c', 'b' ),
1133 'BCassoc' => (object)array( 'a', 'b', 'c' ),
1134 'assoc' => (object)array( 2 => 'a', 0 => 'b', 1 => 'c' ),
1135 'kvp' => array(
1136 (object)array( 'name' => 'x', 'value' => 'a' ),
1137 (object)array( 'name' => 'y', 'value' => 'b' ),
1138 (object)array( 'name' => 'z', 'value' => array( 'c' ) ),
1139 ),
1140 'BCkvp' => array(
1141 (object)array( 'key' => 'x', 'value' => 'a' ),
1142 (object)array( 'key' => 'y', 'value' => 'b' ),
1143 ),
1144 'kvpmerge' => array(
1145 (object)array( 'name' => 'x', 'value' => 'a' ),
1146 (object)array( 'name' => 'y', 'value' => array( 'b' ) ),
1147 (object)array( 'name' => 'z', 'c' => 'd' ),
1148 ),
1149 'emptyDefault' => array(),
1150 'emptyAssoc' => (object)array(),
1151 '_dummy' => 1,
1152 ),
1153 ),
1154
1155 array(
1156 'Strip: all',
1157 $stripArr,
1158 array( 'Strip' => 'all' ),
1159 array(
1160 'foo' => array(
1161 'bar' => array(),
1162 'baz' => array(),
1163 'x' => 'ok',
1164 ),
1165 '_dummy2' => 'foobaz!',
1166 ),
1167 ),
1168 array(
1169 'Strip: base',
1170 $stripArr,
1171 array( 'Strip' => 'base' ),
1172 array(
1173 'foo' => array(
1174 'bar' => array( '_dummy' => 'foobaz' ),
1175 'baz' => array(
1176 ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
1177 ApiResult::META_INDEXED_TAG_NAME => 'itn',
1178 ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
1179 ApiResult::META_TYPE => 'array',
1180 ),
1181 'x' => 'ok',
1182 '_dummy' => 'foobaz',
1183 ),
1184 '_dummy2' => 'foobaz!',
1185 ),
1186 ),
1187 array(
1188 'Strip: bc',
1189 $stripArr,
1190 array( 'Strip' => 'bc' ),
1191 array(
1192 'foo' => array(
1193 'bar' => array(),
1194 'baz' => array(
1195 ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
1196 ApiResult::META_INDEXED_TAG_NAME => 'itn',
1197 ),
1198 'x' => 'ok',
1199 ),
1200 '_dummy2' => 'foobaz!',
1201 ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
1202 ApiResult::META_INDEXED_TAG_NAME => 'itn',
1203 ),
1204 ),
1205
1206 array(
1207 'Custom transform',
1208 array(
1209 'foo' => '?',
1210 'bar' => '?',
1211 '_dummy' => '?',
1212 '_dummy2' => '?',
1213 '_dummy3' => '?',
1214 ApiResult::META_CONTENT => 'foo',
1215 ApiResult::META_PRESERVE_KEYS => array( '_dummy2', '_dummy3' ),
1216 ),
1217 array(
1218 'Custom' => array( $this, 'customTransform' ),
1219 'BC' => array(),
1220 'Types' => array(),
1221 'Strip' => 'all'
1222 ),
1223 array(
1224 '*' => 'FOO',
1225 'bar' => 'BAR',
1226 'baz' => array( 'a', 'b' ),
1227 '_dummy2' => '_DUMMY2',
1228 '_dummy3' => '_DUMMY3',
1229 ApiResult::META_CONTENT => 'bar',
1230 ),
1231 ),
1232 );
1233
1234 }
1235
1236 /**
1237 * Custom transformer for testTransformations
1238 * @param array &$data
1239 * @param array &$metadata
1240 */
1241 public function customTransform( &$data, &$metadata ) {
1242 // Prevent recursion
1243 if ( isset( $metadata['_added'] ) ) {
1244 $metadata[ApiResult::META_TYPE] = 'array';
1245 return;
1246 }
1247
1248 foreach ( $data as $k => $v ) {
1249 $data[$k] = strtoupper( $k );
1250 }
1251 $data['baz'] = array( '_added' => 1, 'z' => 'b', 'y' => 'a' );
1252 $metadata[ApiResult::META_PRESERVE_KEYS][0] = '_dummy';
1253 $data[ApiResult::META_CONTENT] = 'bar';
1254 }
1255
1256 /**
1257 * @covers ApiResult
1258 */
1259 public function testAddMetadataToResultVars() {
1260 $arr = array(
1261 'a' => "foo",
1262 'b' => false,
1263 'c' => 10,
1264 'sequential_numeric_keys' => array( 'a', 'b', 'c' ),
1265 'non_sequential_numeric_keys' => array( 'a', 'b', 4 => 'c' ),
1266 'string_keys' => array(
1267 'one' => 1,
1268 'two' => 2
1269 ),
1270 'object_sequential_keys' => (object)array( 'a', 'b', 'c' ),
1271 '_type' => "should be overwritten in result",
1272 );
1273 $this->assertSame( array(
1274 ApiResult::META_TYPE => 'kvp',
1275 ApiResult::META_KVP_KEY_NAME => 'key',
1276 ApiResult::META_PRESERVE_KEYS => array(
1277 'a', 'b', 'c',
1278 'sequential_numeric_keys', 'non_sequential_numeric_keys',
1279 'string_keys', 'object_sequential_keys'
1280 ),
1281 ApiResult::META_BC_BOOLS => array( 'b' ),
1282 ApiResult::META_INDEXED_TAG_NAME => 'var',
1283 'a' => "foo",
1284 'b' => false,
1285 'c' => 10,
1286 'sequential_numeric_keys' => array(
1287 ApiResult::META_TYPE => 'array',
1288 ApiResult::META_BC_BOOLS => array(),
1289 ApiResult::META_INDEXED_TAG_NAME => 'value',
1290 0 => 'a',
1291 1 => 'b',
1292 2 => 'c',
1293 ),
1294 'non_sequential_numeric_keys' => array(
1295 ApiResult::META_TYPE => 'kvp',
1296 ApiResult::META_KVP_KEY_NAME => 'key',
1297 ApiResult::META_PRESERVE_KEYS => array( 0, 1, 4 ),
1298 ApiResult::META_BC_BOOLS => array(),
1299 ApiResult::META_INDEXED_TAG_NAME => 'var',
1300 0 => 'a',
1301 1 => 'b',
1302 4 => 'c',
1303 ),
1304 'string_keys' => array(
1305 ApiResult::META_TYPE => 'kvp',
1306 ApiResult::META_KVP_KEY_NAME => 'key',
1307 ApiResult::META_PRESERVE_KEYS => array( 'one', 'two' ),
1308 ApiResult::META_BC_BOOLS => array(),
1309 ApiResult::META_INDEXED_TAG_NAME => 'var',
1310 'one' => 1,
1311 'two' => 2,
1312 ),
1313 'object_sequential_keys' => array(
1314 ApiResult::META_TYPE => 'kvp',
1315 ApiResult::META_KVP_KEY_NAME => 'key',
1316 ApiResult::META_PRESERVE_KEYS => array( 0, 1, 2 ),
1317 ApiResult::META_BC_BOOLS => array(),
1318 ApiResult::META_INDEXED_TAG_NAME => 'var',
1319 0 => 'a',
1320 1 => 'b',
1321 2 => 'c',
1322 ),
1323 ), ApiResult::addMetadataToResultVars( $arr ) );
1324 }
1325
1326 /**
1327 * @covers ApiResult
1328 */
1329 public function testDeprecatedFunctions() {
1330 // Ignore ApiResult deprecation warnings during this test
1331 set_error_handler( function ( $errno, $errstr ) use ( &$warnings ) {
1332 if ( preg_match( '/Use of ApiResult::\S+ was deprecated in MediaWiki \d+.\d+\./', $errstr ) ) {
1333 return true;
1334 }
1335 if ( preg_match( '/Use of ApiMain to ApiResult::__construct ' .
1336 'was deprecated in MediaWiki \d+.\d+\./', $errstr ) ) {
1337 return true;
1338 }
1339 return false;
1340 } );
1341 $reset = new ScopedCallback( 'restore_error_handler' );
1342
1343 $context = new DerivativeContext( RequestContext::getMain() );
1344 $context->setConfig( new HashConfig( array(
1345 'APIModules' => array(),
1346 'APIFormatModules' => array(),
1347 'APIMaxResultSize' => 42,
1348 ) ) );
1349 $main = new ApiMain( $context );
1350 $result = TestingAccessWrapper::newFromObject( new ApiResult( $main ) );
1351 $this->assertSame( 42, $result->maxSize );
1352 $this->assertSame( $main->getErrorFormatter(), $result->errorFormatter );
1353 $this->assertSame( $main, $result->mainForContinuation );
1354
1355 $result = new ApiResult( 8388608 );
1356
1357 $result->addContentValue( null, 'test', 'content' );
1358 $result->addContentValue( array( 'foo', 'bar' ), 'test', 'content' );
1359 $result->addIndexedTagName( null, 'itn' );
1360 $result->addSubelementsList( null, array( 'sub' ) );
1361 $this->assertSame( array(
1362 'foo' => array(
1363 'bar' => array(
1364 '*' => 'content',
1365 ),
1366 ),
1367 '*' => 'content',
1368 ), $result->getData() );
1369
1370 $arr = array();
1371 ApiResult::setContent( $arr, 'value' );
1372 ApiResult::setContent( $arr, 'value2', 'foobar' );
1373 $this->assertSame( array(
1374 ApiResult::META_CONTENT => 'content',
1375 'content' => 'value',
1376 'foobar' => array(
1377 ApiResult::META_CONTENT => 'content',
1378 'content' => 'value2',
1379 ),
1380 ), $arr );
1381
1382 $result = new ApiResult( 3 );
1383 $formatter = new ApiErrorFormatter_BackCompat( $result );
1384 $result->setErrorFormatter( $formatter );
1385 $result->disableSizeCheck();
1386 $this->assertTrue( $result->addValue( null, 'foo', '1234567890' ) );
1387 $result->enableSizeCheck();
1388 $this->assertSame( 0, $result->getSize() );
1389 $this->assertFalse( $result->addValue( null, 'foo', '1234567890' ) );
1390
1391 $arr = array( 'foo' => array( 'bar' => 1 ) );
1392 $result->setIndexedTagName_recursive( $arr, 'itn' );
1393 $this->assertSame( array(
1394 'foo' => array(
1395 'bar' => 1,
1396 ApiResult::META_INDEXED_TAG_NAME => 'itn'
1397 ),
1398 ), $arr );
1399
1400 $status = Status::newGood();
1401 $status->fatal( 'parentheses', '1' );
1402 $status->fatal( 'parentheses', '2' );
1403 $status->warning( 'parentheses', '3' );
1404 $status->warning( 'parentheses', '4' );
1405 $this->assertSame( array(
1406 array(
1407 'type' => 'error',
1408 'message' => 'parentheses',
1409 'params' => array(
1410 0 => '1',
1411 ApiResult::META_INDEXED_TAG_NAME => 'param',
1412 ),
1413 ),
1414 array(
1415 'type' => 'error',
1416 'message' => 'parentheses',
1417 'params' => array(
1418 0 => '2',
1419 ApiResult::META_INDEXED_TAG_NAME => 'param',
1420 ),
1421 ),
1422 ApiResult::META_INDEXED_TAG_NAME => 'error',
1423 ), $result->convertStatusToArray( $status, 'error' ) );
1424 $this->assertSame( array(
1425 array(
1426 'type' => 'warning',
1427 'message' => 'parentheses',
1428 'params' => array(
1429 0 => '3',
1430 ApiResult::META_INDEXED_TAG_NAME => 'param',
1431 ),
1432 ),
1433 array(
1434 'type' => 'warning',
1435 'message' => 'parentheses',
1436 'params' => array(
1437 0 => '4',
1438 ApiResult::META_INDEXED_TAG_NAME => 'param',
1439 ),
1440 ),
1441 ApiResult::META_INDEXED_TAG_NAME => 'warning',
1442 ), $result->convertStatusToArray( $status, 'warning' ) );
1443 }
1444
1445 /**
1446 * @covers ApiResult
1447 */
1448 public function testDeprecatedContinuation() {
1449 // Ignore ApiResult deprecation warnings during this test
1450 set_error_handler( function ( $errno, $errstr ) use ( &$warnings ) {
1451 if ( preg_match( '/Use of ApiResult::\S+ was deprecated in MediaWiki \d+.\d+\./', $errstr ) ) {
1452 return true;
1453 }
1454 return false;
1455 } );
1456
1457 $reset = new ScopedCallback( 'restore_error_handler' );
1458 $allModules = array(
1459 new MockApiQueryBase( 'mock1' ),
1460 new MockApiQueryBase( 'mock2' ),
1461 new MockApiQueryBase( 'mocklist' ),
1462 );
1463 $generator = new MockApiQueryBase( 'generator' );
1464
1465 $main = new ApiMain( RequestContext::getMain() );
1466 $result = new ApiResult( 8388608 );
1467 $result->setMainForContinuation( $main );
1468 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1469 $this->assertSame( array( false, $allModules ), $ret );
1470 $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
1471 $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
1472 $result->setGeneratorContinueParam( $generator, 'gcontinue', 3 );
1473 $result->endContinuation( 'raw' );
1474 $result->endContinuation( 'standard' );
1475 $this->assertSame( array(
1476 'mlcontinue' => 2,
1477 'm1continue' => '1|2',
1478 'continue' => '||mock2',
1479 ), $result->getResultData( 'continue' ) );
1480 $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
1481 $this->assertSame( array(
1482 'mock1' => array( 'm1continue' => '1|2' ),
1483 'mocklist' => array( 'mlcontinue' => 2 ),
1484 'generator' => array( 'gcontinue' => 3 ),
1485 ), $result->getResultData( 'query-continue' ) );
1486 $main->setContinuationManager( null );
1487
1488 $result = new ApiResult( 8388608 );
1489 $result->setMainForContinuation( $main );
1490 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1491 $this->assertSame( array( false, $allModules ), $ret );
1492 $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
1493 $result->setGeneratorContinueParam( $generator, 'gcontinue', array( 3, 4 ) );
1494 $result->endContinuation( 'raw' );
1495 $result->endContinuation( 'standard' );
1496 $this->assertSame( array(
1497 'm1continue' => '1|2',
1498 'continue' => '||mock2|mocklist',
1499 ), $result->getResultData( 'continue' ) );
1500 $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
1501 $this->assertSame( array(
1502 'mock1' => array( 'm1continue' => '1|2' ),
1503 'generator' => array( 'gcontinue' => '3|4' ),
1504 ), $result->getResultData( 'query-continue' ) );
1505 $main->setContinuationManager( null );
1506
1507 $result = new ApiResult( 8388608 );
1508 $result->setMainForContinuation( $main );
1509 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1510 $this->assertSame( array( false, $allModules ), $ret );
1511 $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
1512 $result->setGeneratorContinueParam( $generator, 'gcontinue', 3 );
1513 $result->endContinuation( 'raw' );
1514 $result->endContinuation( 'standard' );
1515 $this->assertSame( array(
1516 'mlcontinue' => 2,
1517 'gcontinue' => 3,
1518 'continue' => 'gcontinue||',
1519 ), $result->getResultData( 'continue' ) );
1520 $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
1521 $this->assertSame( array(
1522 'mocklist' => array( 'mlcontinue' => 2 ),
1523 'generator' => array( 'gcontinue' => 3 ),
1524 ), $result->getResultData( 'query-continue' ) );
1525 $main->setContinuationManager( null );
1526
1527 $result = new ApiResult( 8388608 );
1528 $result->setMainForContinuation( $main );
1529 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1530 $this->assertSame( array( false, $allModules ), $ret );
1531 $result->setGeneratorContinueParam( $generator, 'gcontinue', 3 );
1532 $result->endContinuation( 'raw' );
1533 $result->endContinuation( 'standard' );
1534 $this->assertSame( array(
1535 'gcontinue' => 3,
1536 'continue' => 'gcontinue||mocklist',
1537 ), $result->getResultData( 'continue' ) );
1538 $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
1539 $this->assertSame( array(
1540 'generator' => array( 'gcontinue' => 3 ),
1541 ), $result->getResultData( 'query-continue' ) );
1542 $main->setContinuationManager( null );
1543
1544 $result = new ApiResult( 8388608 );
1545 $result->setMainForContinuation( $main );
1546 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1547 $this->assertSame( array( false, $allModules ), $ret );
1548 $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
1549 $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
1550 $result->endContinuation( 'raw' );
1551 $result->endContinuation( 'standard' );
1552 $this->assertSame( array(
1553 'mlcontinue' => 2,
1554 'm1continue' => '1|2',
1555 'continue' => '||mock2',
1556 ), $result->getResultData( 'continue' ) );
1557 $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
1558 $this->assertSame( array(
1559 'mock1' => array( 'm1continue' => '1|2' ),
1560 'mocklist' => array( 'mlcontinue' => 2 ),
1561 ), $result->getResultData( 'query-continue' ) );
1562 $main->setContinuationManager( null );
1563
1564 $result = new ApiResult( 8388608 );
1565 $result->setMainForContinuation( $main );
1566 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1567 $this->assertSame( array( false, $allModules ), $ret );
1568 $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
1569 $result->endContinuation( 'raw' );
1570 $result->endContinuation( 'standard' );
1571 $this->assertSame( array(
1572 'm1continue' => '1|2',
1573 'continue' => '||mock2|mocklist',
1574 ), $result->getResultData( 'continue' ) );
1575 $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
1576 $this->assertSame( array(
1577 'mock1' => array( 'm1continue' => '1|2' ),
1578 ), $result->getResultData( 'query-continue' ) );
1579 $main->setContinuationManager( null );
1580
1581 $result = new ApiResult( 8388608 );
1582 $result->setMainForContinuation( $main );
1583 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1584 $this->assertSame( array( false, $allModules ), $ret );
1585 $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
1586 $result->endContinuation( 'raw' );
1587 $result->endContinuation( 'standard' );
1588 $this->assertSame( array(
1589 'mlcontinue' => 2,
1590 'continue' => '-||mock1|mock2',
1591 ), $result->getResultData( 'continue' ) );
1592 $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
1593 $this->assertSame( array(
1594 'mocklist' => array( 'mlcontinue' => 2 ),
1595 ), $result->getResultData( 'query-continue' ) );
1596 $main->setContinuationManager( null );
1597
1598 $result = new ApiResult( 8388608 );
1599 $result->setMainForContinuation( $main );
1600 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1601 $this->assertSame( array( false, $allModules ), $ret );
1602 $result->endContinuation( 'raw' );
1603 $result->endContinuation( 'standard' );
1604 $this->assertSame( null, $result->getResultData( 'continue' ) );
1605 $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
1606 $this->assertSame( null, $result->getResultData( 'query-continue' ) );
1607 $main->setContinuationManager( null );
1608
1609 $result = new ApiResult( 8388608 );
1610 $result->setMainForContinuation( $main );
1611 $ret = $result->beginContinuation( '||mock2', $allModules, array( 'mock1', 'mock2' ) );
1612 $this->assertSame(
1613 array( false, array_values( array_diff_key( $allModules, array( 1 => 1 ) ) ) ),
1614 $ret
1615 );
1616 $main->setContinuationManager( null );
1617
1618 $result = new ApiResult( 8388608 );
1619 $result->setMainForContinuation( $main );
1620 $ret = $result->beginContinuation( '-||', $allModules, array( 'mock1', 'mock2' ) );
1621 $this->assertSame(
1622 array( true, array_values( array_diff_key( $allModules, array( 0 => 0, 1 => 1 ) ) ) ),
1623 $ret
1624 );
1625 $main->setContinuationManager( null );
1626
1627 $result = new ApiResult( 8388608 );
1628 $result->setMainForContinuation( $main );
1629 try {
1630 $result->beginContinuation( 'foo', $allModules, array( 'mock1', 'mock2' ) );
1631 $this->fail( 'Expected exception not thrown' );
1632 } catch ( UsageException $ex ) {
1633 $this->assertSame(
1634 'Invalid continue param. You should pass the original value returned by the previous query',
1635 $ex->getMessage(),
1636 'Expected exception'
1637 );
1638 }
1639 $main->setContinuationManager( null );
1640
1641 $result = new ApiResult( 8388608 );
1642 $result->setMainForContinuation( $main );
1643 $result->beginContinuation( '||mock2', array_slice( $allModules, 0, 2 ),
1644 array( 'mock1', 'mock2' ) );
1645 try {
1646 $result->setContinueParam( $allModules[1], 'm2continue', 1 );
1647 $this->fail( 'Expected exception not thrown' );
1648 } catch ( UnexpectedValueException $ex ) {
1649 $this->assertSame(
1650 'Module \'mock2\' was not supposed to have been executed, but it was executed anyway',
1651 $ex->getMessage(),
1652 'Expected exception'
1653 );
1654 }
1655 try {
1656 $result->setContinueParam( $allModules[2], 'mlcontinue', 1 );
1657 $this->fail( 'Expected exception not thrown' );
1658 } catch ( UnexpectedValueException $ex ) {
1659 $this->assertSame(
1660 'Module \'mocklist\' called ApiContinuationManager::addContinueParam ' .
1661 'but was not passed to ApiContinuationManager::__construct',
1662 $ex->getMessage(),
1663 'Expected exception'
1664 );
1665 }
1666 $main->setContinuationManager( null );
1667
1668 }
1669
1670 public function testObjectSerialization() {
1671 $arr = array();
1672 ApiResult::setValue( $arr, 'foo', (object)array( 'a' => 1, 'b' => 2 ) );
1673 $this->assertSame( array(
1674 'a' => 1,
1675 'b' => 2,
1676 ApiResult::META_TYPE => 'assoc',
1677 ), $arr['foo'] );
1678
1679 $arr = array();
1680 ApiResult::setValue( $arr, 'foo', new ApiResultTestStringifiableObject() );
1681 $this->assertSame( 'Ok', $arr['foo'] );
1682
1683 $arr = array();
1684 ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject( 'Ok' ) );
1685 $this->assertSame( 'Ok', $arr['foo'] );
1686
1687 try {
1688 $arr = array();
1689 ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject(
1690 new ApiResultTestStringifiableObject()
1691 ) );
1692 $this->fail( 'Expected exception not thrown' );
1693 } catch ( UnexpectedValueException $ex ) {
1694 $this->assertSame(
1695 'ApiResultTestSerializableObject::serializeForApiResult() ' .
1696 'returned an object of class ApiResultTestStringifiableObject',
1697 $ex->getMessage(),
1698 'Expected exception'
1699 );
1700 }
1701
1702 try {
1703 $arr = array();
1704 ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject( NAN ) );
1705 $this->fail( 'Expected exception not thrown' );
1706 } catch ( UnexpectedValueException $ex ) {
1707 $this->assertSame(
1708 'ApiResultTestSerializableObject::serializeForApiResult() ' .
1709 'returned an invalid value: Cannot add non-finite floats to ApiResult',
1710 $ex->getMessage(),
1711 'Expected exception'
1712 );
1713 }
1714
1715 $arr = array();
1716 ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject(
1717 array(
1718 'one' => new ApiResultTestStringifiableObject( '1' ),
1719 'two' => new ApiResultTestSerializableObject( 2 ),
1720 )
1721 ) );
1722 $this->assertSame( array(
1723 'one' => '1',
1724 'two' => 2,
1725 ), $arr['foo'] );
1726 }
1727
1728 }
1729
1730 class ApiResultTestStringifiableObject {
1731 private $ret;
1732
1733 public function __construct( $ret = 'Ok' ) {
1734 $this->ret = $ret;
1735 }
1736
1737 public function __toString() {
1738 return $this->ret;
1739 }
1740 }
1741
1742 class ApiResultTestSerializableObject {
1743 private $ret;
1744
1745 public function __construct( $ret ) {
1746 $this->ret = $ret;
1747 }
1748
1749 public function __toString() {
1750 return "Fail";
1751 }
1752
1753 public function serializeForApiResult() {
1754 return $this->ret;
1755 }
1756 }