1--TEST--
2MongoDB\BSON\toPHP(): Tests from serialization specification
3--FILE--
4<?php
5
6require_once __DIR__ . '/../utils/tools.php';
7
8class MyClass
9{
10}
11
12class YourClass implements MongoDB\BSON\Unserializable
13{
14    function bsonUnserialize(array $data)
15    {
16        foreach ($data as $key => $value) {
17            $this->$key = $value;
18        }
19        $this->unserialized = true;
20    }
21}
22
23class OurClass implements MongoDB\BSON\Persistable
24{
25    function bsonSerialize()
26    {
27        // Not tested with this test, so return empty array
28        return array();
29    }
30
31    function bsonUnserialize(array $data)
32    {
33        foreach ($data as $key => $value) {
34            $this->$key = $value;
35        }
36        $this->unserialized = true;
37    }
38}
39
40class TheirClass extends OurClass
41{
42}
43
44// Create base64-encoded class names for __pclass field's binary data
45$bMyClass = base64_encode('MyClass');
46$bYourClass = base64_encode('YourClass');
47$bOurClass = base64_encode('OurClass');
48$bTheirClass = base64_encode('TheirClass');
49$bInterface = base64_encode('MongoDB\BSON\Unserializable');
50
51$testGroups = array(
52    array(
53        'name' => 'DEFAULT TYPEMAP',
54        'typemap' => array(),
55        'tests' => array(
56            '{ "foo": "yes", "bar" : false }',
57            '{ "foo": "no", "array" : [ 5, 6 ] }',
58            '{ "foo": "no", "obj" : { "embedded" : 4.125 } }',
59            '{ "foo": "yes", "__pclass": "MyClass" }',
60            '{ "foo": "yes", "__pclass": { "$binary": "' . $bMyClass . '", "$type": "80" } }',
61            '{ "foo": "yes", "__pclass": { "$binary": "' . $bYourClass . '", "$type": "80" } }',
62            '{ "foo": "yes", "__pclass": { "$binary": "' . $bOurClass . '", "$type": "80" } }',
63            '{ "foo": "yes", "__pclass": { "$binary": "' . $bYourClass . '", "$type": "44" } }',
64        ),
65    ),
66    array(
67        'name' => 'NONEXISTING CLASS',
68        'typemap' => array('root' => 'MissingClass'),
69        'tests' => array(
70            '{ "foo": "yes" }',
71        ),
72    ),
73    array(
74        'name' => 'DOES NOT IMPLEMENT UNSERIALIZABLE',
75        'typemap' => array('root' => 'MyClass'),
76        'tests' => array(
77            '{ "foo": "yes", "__pclass": { "$binary": "' . $bMyClass . '", "$type": "80" } }',
78        ),
79    ),
80    array(
81        'name' => 'IS NOT A CONCRETE CLASS',
82        'typemap' => array('root' => 'MongoDB\BSON\Unserializable'),
83        'tests' => array(
84            '{ "foo": "yes" }',
85        ),
86    ),
87    array(
88        'name' => 'IS NOT A CONCRETE CLASS VIA PCLASS',
89        'typemap' => array('root' => 'YourClass'),
90        'tests' => array(
91            '{ "foo": "yes", "__pclass" : { "$binary": "' . $bInterface . '", "$type": "80" } }',
92        ),
93    ),
94    array(
95        'name' => 'PCLASS OVERRIDES TYPEMAP (1)',
96        'typemap' => array('root' => 'YourClass'),
97        'tests' => array(
98            '{ "foo": "yes", "__pclass" : { "$binary": "' . $bMyClass . '", "$type": "80" } }',
99            '{ "foo": "yes", "__pclass" : { "$binary": "' . $bOurClass . '", "$type": "80" } }',
100            '{ "foo": "yes", "__pclass" : { "$binary": "' . $bTheirClass . '", "$type": "80" } }',
101            '{ "foo": "yes", "__pclass" : { "$binary": "' . $bYourClass . '", "$type": "80" } }',
102        ),
103    ),
104    array(
105        'name' => 'PCLASS OVERRIDES TYPEMAP (2)',
106        'typemap' => array('root' => 'OurClass'),
107        'tests' => array(
108            '{ "foo": "yes", "__pclass" : { "$binary": "' . $bTheirClass . '", "$type": "80" } }',
109        ),
110    ),
111    array(
112        'name' => 'OBJECTS AS ARRAY',
113        'typemap' => array('root' => 'array', 'document' => 'array'),
114        'tests' => array(
115            '{ "foo": "yes", "bar" : false }',
116            '{ "foo": "no", "array" : [ 5, 6 ] }',
117            '{ "foo": "no", "obj" : { "embedded" : 4.125 } }',
118            '{ "foo": "yes", "__pclass": "MyClass" }',
119            '{ "foo": "yes", "__pclass" : { "$binary": "' . $bMyClass . '", "$type": "80" } }',
120            '{ "foo": "yes", "__pclass" : { "$binary": "' . $bOurClass . '", "$type": "80" } }',
121        ),
122    ),
123    array(
124        'name' => 'OBJECTS AS STDCLASS',
125        'typemap' => array('root' => 'object', 'document' => 'object'),
126        'tests' => array(
127            '{ "foo": "yes", "__pclass" : { "$binary": "' . $bMyClass . '", "$type": "80" } }',
128            '{ "foo": "yes", "__pclass" : { "$binary": "' . $bOurClass . '", "$type": "80" } }',
129        ),
130    ),
131);
132
133foreach ($testGroups as $testGroup) {
134    printf("=== %s ===\n\n", $testGroup['name']);
135
136    foreach ($testGroup['tests'] as $test) {
137        echo $test, "\n";
138
139        $bson = fromJSON($test);
140        try {
141            var_dump(toPHP($bson, $testGroup['typemap']));
142        } catch (MongoDB\Driver\Exception\Exception $e) {
143            echo $e->getMessage(), "\n";
144        }
145
146        echo "\n";
147    }
148
149    echo "\n";
150}
151
152?>
153===DONE===
154<?php exit(0); ?>
155--EXPECTF--
156=== DEFAULT TYPEMAP ===
157
158{ "foo": "yes", "bar" : false }
159object(stdClass)#%d (2) {
160  ["foo"]=>
161  string(3) "yes"
162  ["bar"]=>
163  bool(false)
164}
165
166{ "foo": "no", "array" : [ 5, 6 ] }
167object(stdClass)#%d (2) {
168  ["foo"]=>
169  string(2) "no"
170  ["array"]=>
171  array(2) {
172    [0]=>
173    int(5)
174    [1]=>
175    int(6)
176  }
177}
178
179{ "foo": "no", "obj" : { "embedded" : 4.125 } }
180object(stdClass)#%d (2) {
181  ["foo"]=>
182  string(2) "no"
183  ["obj"]=>
184  object(stdClass)#%d (1) {
185    ["embedded"]=>
186    float(4.125)
187  }
188}
189
190{ "foo": "yes", "__pclass": "MyClass" }
191object(stdClass)#%d (2) {
192  ["foo"]=>
193  string(3) "yes"
194  ["__pclass"]=>
195  string(7) "MyClass"
196}
197
198{ "foo": "yes", "__pclass": { "$binary": "TXlDbGFzcw==", "$type": "80" } }
199object(stdClass)#%d (2) {
200  ["foo"]=>
201  string(3) "yes"
202  ["__pclass"]=>
203  object(MongoDB\BSON\Binary)#%d (2) {
204    ["data"]=>
205    string(7) "MyClass"
206    ["type"]=>
207    int(128)
208  }
209}
210
211{ "foo": "yes", "__pclass": { "$binary": "WW91ckNsYXNz", "$type": "80" } }
212object(stdClass)#%d (2) {
213  ["foo"]=>
214  string(3) "yes"
215  ["__pclass"]=>
216  object(MongoDB\BSON\Binary)#%d (2) {
217    ["data"]=>
218    string(9) "YourClass"
219    ["type"]=>
220    int(128)
221  }
222}
223
224{ "foo": "yes", "__pclass": { "$binary": "T3VyQ2xhc3M=", "$type": "80" } }
225object(OurClass)#%d (3) {
226  ["foo"]=>
227  string(3) "yes"
228  ["__pclass"]=>
229  object(MongoDB\BSON\Binary)#%d (2) {
230    ["data"]=>
231    string(8) "OurClass"
232    ["type"]=>
233    int(128)
234  }
235  ["unserialized"]=>
236  bool(true)
237}
238
239{ "foo": "yes", "__pclass": { "$binary": "WW91ckNsYXNz", "$type": "44" } }
240object(stdClass)#%d (2) {
241  ["foo"]=>
242  string(3) "yes"
243  ["__pclass"]=>
244  object(MongoDB\BSON\Binary)#%d (2) {
245    ["data"]=>
246    string(9) "YourClass"
247    ["type"]=>
248    int(68)
249  }
250}
251
252
253=== NONEXISTING CLASS ===
254
255{ "foo": "yes" }
256Class MissingClass does not exist
257
258
259=== DOES NOT IMPLEMENT UNSERIALIZABLE ===
260
261{ "foo": "yes", "__pclass": { "$binary": "TXlDbGFzcw==", "$type": "80" } }
262Class MyClass does not implement MongoDB\BSON\Unserializable
263
264
265=== IS NOT A CONCRETE CLASS ===
266
267{ "foo": "yes" }
268Class MongoDB\BSON\Unserializable is not instantiatable
269
270
271=== IS NOT A CONCRETE CLASS VIA PCLASS ===
272
273{ "foo": "yes", "__pclass" : { "$binary": "TW9uZ29EQlxCU09OXFVuc2VyaWFsaXphYmxl", "$type": "80" } }
274object(YourClass)#%d (3) {
275  ["foo"]=>
276  string(3) "yes"
277  ["__pclass"]=>
278  object(MongoDB\BSON\Binary)#%d (2) {
279    ["data"]=>
280    string(27) "MongoDB\BSON\Unserializable"
281    ["type"]=>
282    int(128)
283  }
284  ["unserialized"]=>
285  bool(true)
286}
287
288
289=== PCLASS OVERRIDES TYPEMAP (1) ===
290
291{ "foo": "yes", "__pclass" : { "$binary": "TXlDbGFzcw==", "$type": "80" } }
292object(YourClass)#%d (3) {
293  ["foo"]=>
294  string(3) "yes"
295  ["__pclass"]=>
296  object(MongoDB\BSON\Binary)#%d (2) {
297    ["data"]=>
298    string(7) "MyClass"
299    ["type"]=>
300    int(128)
301  }
302  ["unserialized"]=>
303  bool(true)
304}
305
306{ "foo": "yes", "__pclass" : { "$binary": "T3VyQ2xhc3M=", "$type": "80" } }
307object(OurClass)#%d (3) {
308  ["foo"]=>
309  string(3) "yes"
310  ["__pclass"]=>
311  object(MongoDB\BSON\Binary)#%d (2) {
312    ["data"]=>
313    string(8) "OurClass"
314    ["type"]=>
315    int(128)
316  }
317  ["unserialized"]=>
318  bool(true)
319}
320
321{ "foo": "yes", "__pclass" : { "$binary": "VGhlaXJDbGFzcw==", "$type": "80" } }
322object(TheirClass)#%d (3) {
323  ["foo"]=>
324  string(3) "yes"
325  ["__pclass"]=>
326  object(MongoDB\BSON\Binary)#%d (2) {
327    ["data"]=>
328    string(10) "TheirClass"
329    ["type"]=>
330    int(128)
331  }
332  ["unserialized"]=>
333  bool(true)
334}
335
336{ "foo": "yes", "__pclass" : { "$binary": "WW91ckNsYXNz", "$type": "80" } }
337object(YourClass)#%d (3) {
338  ["foo"]=>
339  string(3) "yes"
340  ["__pclass"]=>
341  object(MongoDB\BSON\Binary)#%d (2) {
342    ["data"]=>
343    string(9) "YourClass"
344    ["type"]=>
345    int(128)
346  }
347  ["unserialized"]=>
348  bool(true)
349}
350
351
352=== PCLASS OVERRIDES TYPEMAP (2) ===
353
354{ "foo": "yes", "__pclass" : { "$binary": "VGhlaXJDbGFzcw==", "$type": "80" } }
355object(TheirClass)#%d (3) {
356  ["foo"]=>
357  string(3) "yes"
358  ["__pclass"]=>
359  object(MongoDB\BSON\Binary)#%d (2) {
360    ["data"]=>
361    string(10) "TheirClass"
362    ["type"]=>
363    int(128)
364  }
365  ["unserialized"]=>
366  bool(true)
367}
368
369
370=== OBJECTS AS ARRAY ===
371
372{ "foo": "yes", "bar" : false }
373array(2) {
374  ["foo"]=>
375  string(3) "yes"
376  ["bar"]=>
377  bool(false)
378}
379
380{ "foo": "no", "array" : [ 5, 6 ] }
381array(2) {
382  ["foo"]=>
383  string(2) "no"
384  ["array"]=>
385  array(2) {
386    [0]=>
387    int(5)
388    [1]=>
389    int(6)
390  }
391}
392
393{ "foo": "no", "obj" : { "embedded" : 4.125 } }
394array(2) {
395  ["foo"]=>
396  string(2) "no"
397  ["obj"]=>
398  array(1) {
399    ["embedded"]=>
400    float(4.125)
401  }
402}
403
404{ "foo": "yes", "__pclass": "MyClass" }
405array(2) {
406  ["foo"]=>
407  string(3) "yes"
408  ["__pclass"]=>
409  string(7) "MyClass"
410}
411
412{ "foo": "yes", "__pclass" : { "$binary": "TXlDbGFzcw==", "$type": "80" } }
413array(2) {
414  ["foo"]=>
415  string(3) "yes"
416  ["__pclass"]=>
417  object(MongoDB\BSON\Binary)#%d (2) {
418    ["data"]=>
419    string(7) "MyClass"
420    ["type"]=>
421    int(128)
422  }
423}
424
425{ "foo": "yes", "__pclass" : { "$binary": "T3VyQ2xhc3M=", "$type": "80" } }
426array(2) {
427  ["foo"]=>
428  string(3) "yes"
429  ["__pclass"]=>
430  object(MongoDB\BSON\Binary)#%d (2) {
431    ["data"]=>
432    string(8) "OurClass"
433    ["type"]=>
434    int(128)
435  }
436}
437
438
439=== OBJECTS AS STDCLASS ===
440
441{ "foo": "yes", "__pclass" : { "$binary": "TXlDbGFzcw==", "$type": "80" } }
442object(stdClass)#%d (2) {
443  ["foo"]=>
444  string(3) "yes"
445  ["__pclass"]=>
446  object(MongoDB\BSON\Binary)#%d (2) {
447    ["data"]=>
448    string(7) "MyClass"
449    ["type"]=>
450    int(128)
451  }
452}
453
454{ "foo": "yes", "__pclass" : { "$binary": "T3VyQ2xhc3M=", "$type": "80" } }
455object(stdClass)#%d (2) {
456  ["foo"]=>
457  string(3) "yes"
458  ["__pclass"]=>
459  object(MongoDB\BSON\Binary)#%d (2) {
460    ["data"]=>
461    string(8) "OurClass"
462    ["type"]=>
463    int(128)
464  }
465}
466
467
468===DONE===
469