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