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