ServerTest::testClientMulticall4()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 29
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 18
nc 2
nop 0
dl 0
loc 29
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
include_once __DIR__ . '/../lib/xmlrpc_wrappers.inc';
4
5
include_once __DIR__ . '/ServerAwareTestCase.php';
6
7
/**
8
 * Tests which involve interaction with the server - carried out via the client.
9
 * They are run against the server found in demo/server.php.
10
 * Includes testing of (some of) the Wrapper class
11
 */
12
class ServerTest extends PhpXmlRpc_ServerAwareTestCase
13
{
14
    /** @var xmlrpc_client $client */
15
    protected $client = null;
16
    protected $method = 'http';
17
    protected $timeout = 10;
18
    protected $request_compression = null;
19
    protected $accepted_compression = '';
20
21
    protected static $failed_tests = array();
22
    protected static $originalInternalEncoding;
23
24
    /**
25
     * @todo instead of overriding fail via _fail, implement Yoast\PHPUnitPolyfills\TestListeners\TestListenerDefaultImplementation
26
     */
27
    public static function _fail($message = '')
28
    {
29
        // save in a static var that this particular test has failed
30
        // (but only if not called from subclass objects / multitests)
31
        if (function_exists('debug_backtrace') && strtolower(get_called_class()) == 'servertest') {
32
            $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
33
            for ($i = 0; $i < count($trace); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
34
                if (strpos($trace[$i]['function'], 'test') === 0) {
35
                    self::$failed_tests[$trace[$i]['function']] = true;
36
                    break;
37
                }
38
            }
39
        }
40
41
        parent::_fail($message);
0 ignored issues
show
Unused Code introduced by
The call to PhpXmlRpc_PolyfillTestCase::_fail() has too many arguments starting with $message. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

41
        parent::/** @scrutinizer ignore-call */ 
42
                _fail($message);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
42
    }
43
44
    public static function set_up_before_class()
45
    {
46
        parent::set_up_before_class();
47
48
        self::$originalInternalEncoding = \PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding;
49
    }
50
51
    public function set_up()
52
    {
53
        parent::set_up();
54
55
        // these 2 values are injected into the client when calling `send`, and are modified by some tests - reset them
56
        $this->timeout = 10;
57
        $this->method = 'http';
58
59
        $this->client = $this->getClient();
60
61
        /// @todo replace with setOption when dropping the BC layer
62
        $this->client->request_compression = $this->request_compression;
0 ignored issues
show
Bug Best Practice introduced by
The property $request_compression is declared protected in PhpXmlRpc\Client. Since you implement __set, consider adding a @property or @property-write.
Loading history...
63
        $this->client->accepted_compression = $this->accepted_compression;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->accepted_compression of type string is incompatible with the declared type array of property $accepted_compression.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
Bug Best Practice introduced by
The property $accepted_compression is declared protected in PhpXmlRpc\Client. Since you implement __set, consider adding a @property or @property-write.
Loading history...
64
    }
65
66
    public function tear_down()
67
    {
68
        \PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = self::$originalInternalEncoding;
69
70
        parent::tear_down();
71
    }
72
73
    /**
74
     * @param PhpXmlRpc\Request|array $msg
75
     * @param int|int[] $errorCode expected error codes
76
     * @param bool $returnResponse
77
     * @return mixed|\PhpXmlRpc\Response|\PhpXmlRpc\Response[]|\PhpXmlRpc\Value|string|null
78
     * @todo allo callers to disable checking of faultCode
79
     */
80
    protected function send($msg, $errorCode = 0, $returnResponse = false)
81
    {
82
        /// @todo move to injecting timeout and method into `getClient`, use the non-legacy API calling convention
83
        $r = $this->client->send($msg, $this->timeout, $this->method);
84
        // for multicall, return directly array of responses
85
        if (is_array($r)) {
86
            return $r;
87
        }
88
        $this->validateResponse($r);
89
        if (is_array($errorCode)) {
90
            $this->assertContains($r->faultCode(), $errorCode, 'Error ' . $r->faultCode() . ' connecting to server: ' . $r->faultString());
91
        } else {
92
            $this->assertEquals($errorCode, $r->faultCode(), 'Error ' . $r->faultCode() . ' connecting to server: ' . $r->faultString());
93
        }
94
        if (!$r->faultCode()) {
95
            if ($returnResponse) {
96
                return $r;
97
            } else {
98
                return $r->value();
99
            }
100
        } else {
101
            return null;
102
        }
103
    }
104
105
    protected function validateResponse($r)
106
    {
107
        // to be implemented in subclasses
108
    }
109
110
    /**
111
     * Adds (and replaces) query params to the url currently used by the client
112
     * @param array $data
113
     */
114
    protected function addQueryParams($data)
115
    {
116
        $query = parse_url($this->client->path, PHP_URL_QUERY);
117
        parse_str($query, $vars);
118
        $query = http_build_query(array_merge($vars, $data));
119
        $this->client->path = parse_url($this->client->path, PHP_URL_PATH) . '?' . $query;
120
    }
121
122
    public function testString()
123
    {
124
        $sendString = "here are 3 \"entities\": < > & " .
125
            "and here's a dollar sign: \$pretendvarname and a backslash too: " . chr(92) .
126
            " - isn't that great? \\\"hackery\\\" at it's best " .
127
            " also don't want to miss out on \$item[0]. " .
128
            "The real weird stuff follows: CRLF here" . chr(13) . chr(10) .
129
            "a simple CR here" . chr(13) .
130
            "a simple LF here" . chr(10) .
131
            "and then LFCR" . chr(10) . chr(13) .
132
            "last but not least weird names: G" . chr(252) . "nter, El" . chr(232) . "ne, and an xml comment closing tag: -->";
133
        $m = new xmlrpcmsg('examples.stringecho', array(
134
            new xmlrpcval($sendString, 'string'),
135
        ));
136
        $v = $this->send($m);
137
        if ($v) {
138
            // when sending/receiving non-US-ASCII encoded strings, XML says cr-lf can be normalized.
139
            // so we relax our tests...
140
            $l1 = strlen($sendString);
141
            $l2 = strlen($v->scalarval());
0 ignored issues
show
Bug introduced by
The method scalarval() does not exist on PhpXmlRpc\Response. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

141
            $l2 = strlen($v->/** @scrutinizer ignore-call */ scalarval());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
142
            if ($l1 == $l2) {
143
                $this->assertEquals($sendString, $v->scalarval());
144
            } else {
145
                $this->assertEquals(str_replace(array("\r\n", "\r"), array("\n", "\n"), $sendString), $v->scalarval());
146
            }
147
        }
148
    }
149
150
    public function testLatin1String()
151
    {
152
        $sendString =
153
            "last but not least weird names: G" . chr(252) . "nter, El" . chr(232) . "ne";
154
        $x = '<?xml version="1.0" encoding="ISO-8859-1"?><methodCall><methodName>examples.stringecho</methodName><params><param><value>'.
155
            $sendString.
156
            '</value></param></params></methodCall>';
157
        $v = $this->send($x);
0 ignored issues
show
Bug introduced by
$x of type string is incompatible with the type PhpXmlRpc\Request|array expected by parameter $msg of ServerTest::send(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

157
        $v = $this->send(/** @scrutinizer ignore-type */ $x);
Loading history...
158
        if ($v) {
159
            $this->assertEquals($sendString, $v->scalarval());
160
        }
161
    }
162
163
    public function testExoticCharsetsRequests()
164
    {
165
        // note that we should disable this call also when mbstring is missing server-side
166
        if (!function_exists('mb_convert_encoding')) {
167
            $this->markTestSkipped('Miss mbstring extension to test exotic charsets');
168
        }
169
170
        $sendString = 'κόσμε'; // Greek word 'kosme'
171
        $str = '<?xml version="1.0" encoding="_ENC_"?>
172
<methodCall>
173
    <methodName>examples.stringecho</methodName>
174
    <params>
175
        <param>
176
        <value><string>'.$sendString.'</string></value>
177
        </param>
178
    </params>
179
</methodCall>';
180
181
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'UTF-8';
182
        // This test is known to fail with old mbstring versions, at least the ones we get with php 5.4, 5.5 as present
183
        // in the CI test vms
184
        if (version_compare(PHP_VERSION, '5.6.0', '>=')) {
185
            // we have to set the encoding declaration either in the http header or xml prolog, as mb_detect_encoding
186
            // (used on the server side) will fail recognizing these 2 charsets
187
            $v = $this->send(mb_convert_encoding(str_replace('_ENC_', 'UCS-4', $str), 'UCS-4', 'UTF-8'));
0 ignored issues
show
Bug introduced by
It seems like mb_convert_encoding(str_...str), 'UCS-4', 'UTF-8') can also be of type string; however, parameter $msg of ServerTest::send() does only seem to accept PhpXmlRpc\Request|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

187
            $v = $this->send(/** @scrutinizer ignore-type */ mb_convert_encoding(str_replace('_ENC_', 'UCS-4', $str), 'UCS-4', 'UTF-8'));
Loading history...
188
            $this->assertEquals($sendString, $v->scalarval());
189
        }
190
        $v = $this->send(mb_convert_encoding(str_replace('_ENC_', 'UTF-16', $str), 'UTF-16', 'UTF-8'));
191
        $this->assertEquals($sendString, $v->scalarval());
192
        //PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
193
    }
194
195
    public function testExoticCharsetsRequests2()
196
    {
197
        // note that we should disable this call also when mbstring is missing server-side
198
        if (!function_exists('mb_convert_encoding')) {
199
            $this->markTestSkipped('Miss mbstring extension to test exotic charsets');
200
        }
201
202
        $sendString = '安室奈美恵'; // Japanese name "Namie Amuro"
203
        $str = '<?xml version="1.0"?>
204
<methodCall>
205
    <methodName>examples.stringecho</methodName>
206
    <params>
207
        <param>
208
        <value><string>'.$sendString.'</string></value>
209
        </param>
210
    </params>
211
</methodCall>';
212
213
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'UTF-8';
214
        // no encoding declaration either in the http header or xml prolog, let mb_detect_encoding
215
        // (used on the server side) sort it out
216
        $this->addQueryParams(array('DETECT_ENCODINGS' => array('EUC-JP', 'UTF-8')));
217
        $v = $this->send(mb_convert_encoding($str, 'EUC-JP', 'UTF-8'));
0 ignored issues
show
Bug introduced by
It seems like mb_convert_encoding($str, 'EUC-JP', 'UTF-8') can also be of type string; however, parameter $msg of ServerTest::send() does only seem to accept PhpXmlRpc\Request|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

217
        $v = $this->send(/** @scrutinizer ignore-type */ mb_convert_encoding($str, 'EUC-JP', 'UTF-8'));
Loading history...
218
        //PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
219
        $this->assertEquals($sendString, $v->scalarval());
220
    }
221
222
    public function testExoticCharsetsRequests3()
223
    {
224
        // note that we should disable this call also when mbstring is missing server-side
225
        if (!function_exists('mb_convert_encoding')) {
226
            $this->markTestSkipped('Miss mbstring extension to test exotic charsets');
227
        }
228
229
        // the warning suppression is due to utf8_decode being deprecated in php 8.2
230
        $sendString = @utf8_decode('élève');
231
        $str = '<?xml version="1.0"?>
232
<methodCall>
233
    <methodName>examples.stringecho</methodName>
234
    <params>
235
        <param>
236
        <value><string>'.$sendString.'</string></value>
237
        </param>
238
    </params>
239
</methodCall>';
240
241
        // no encoding declaration either in the http header or xml prolog, let mb_detect_encoding
242
        // (used on the server side) sort it out
243
        $this->addQueryParams(array('DETECT_ENCODINGS' => array('ISO-8859-1', 'UTF-8')));
244
        $v = $this->send($str);
0 ignored issues
show
Bug introduced by
$str of type string is incompatible with the type PhpXmlRpc\Request|array expected by parameter $msg of ServerTest::send(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

244
        $v = $this->send(/** @scrutinizer ignore-type */ $str);
Loading history...
245
        $this->assertEquals($sendString, $v->scalarval());
246
    }
247
248
    /*public function testLatin1Method()
249
    {
250
        $f = new xmlrpcmsg("tests.iso88591methodname." . chr(224) . chr(252) . chr(232), array(
251
            new xmlrpcval('hello')
252
        ));
253
        $v = $this->send($f);
254
        if ($v) {
255
            $this->assertEquals('hello', $v->scalarval());
256
        }
257
    }*/
258
259
    public function testUtf8Method()
260
    {
261
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'UTF-8';
262
        $m = new xmlrpcmsg("tests.utf8methodname." . 'κόσμε', array(
263
            new xmlrpcval('hello')
264
        ));
265
        $v = $this->send($m);
266
        //PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
267
        if ($v) {
268
            $this->assertEquals('hello', $v->scalarval());
269
        }
270
    }
271
272
    public function testAddingDoubles()
273
    {
274
        // note that rounding errors mean we keep precision to sensible levels here ;-)
275
        $a = 12.13;
276
        $b = -23.98;
277
        $m = new xmlrpcmsg('examples.addtwodouble', array(
278
            new xmlrpcval($a, 'double'),
279
            new xmlrpcval($b, 'double'),
280
        ));
281
        $v = $this->send($m);
282
        if ($v) {
283
            $this->assertEquals($a + $b, $v->scalarval());
284
        }
285
    }
286
287
    public function testAdding()
288
    {
289
        $m = new xmlrpcmsg('examples.addtwo', array(
290
            new xmlrpcval(12, 'int'),
291
            new xmlrpcval(-23, 'int'),
292
        ));
293
        $v = $this->send($m);
294
        if ($v) {
295
            $this->assertEquals(12 - 23, $v->scalarval());
296
        }
297
    }
298
299
    public function testInvalidNumber()
300
    {
301
        $m = new xmlrpcmsg('examples.addtwo', array(
302
            new xmlrpcval('fred', 'int'),
303
            new xmlrpcval("\"; exec('ls')", 'int'),
304
        ));
305
        $v = $this->send($m);
306
        /// @todo a specific fault should be generated here by the server, which we can check
307
        if ($v) {
308
            $this->assertEquals(0, $v->scalarval());
309
        }
310
    }
311
312
    public function testUnknownMethod()
313
    {
314
        $m = new xmlrpcmsg('examples.a_very_unlikely.method', array());
315
        $this->send($m, \PhpXmlRpc\PhpXmlRpc::$xmlrpcerr['unknown_method']);
316
    }
317
318
    public function testBoolean()
319
    {
320
        $m = new xmlrpcmsg('examples.invertBooleans', array(
321
            new xmlrpcval(array(
322
                new xmlrpcval(true, 'boolean'),
323
                new xmlrpcval(false, 'boolean'),
324
                new xmlrpcval(1, 'boolean'),
325
                new xmlrpcval(0, 'boolean')
326
            ),
327
                'array'
328
            ),));
329
        $answer = '0101';
330
        $v = $this->send($m);
331
        if ($v) {
332
            $sz = $v->arraysize();
0 ignored issues
show
Bug introduced by
The method arraysize() does not exist on PhpXmlRpc\Response. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

332
            /** @scrutinizer ignore-call */ 
333
            $sz = $v->arraysize();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Deprecated Code introduced by
The function PhpXmlRpc\Value::arraySize() has been deprecated: use count() instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

332
            $sz = /** @scrutinizer ignore-deprecated */ $v->arraysize();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
333
            $got = '';
334
            for ($i = 0; $i < $sz; $i++) {
335
                $b = $v->arraymem($i);
0 ignored issues
show
Deprecated Code introduced by
The function PhpXmlRpc\Value::arrayMem() has been deprecated: use array access, e.g. $val[$key] ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

335
                $b = /** @scrutinizer ignore-deprecated */ $v->arraymem($i);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
Bug introduced by
The method arraymem() does not exist on PhpXmlRpc\Response. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

335
                /** @scrutinizer ignore-call */ 
336
                $b = $v->arraymem($i);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
336
                if ($b->scalarval()) {
337
                    $got .= '1';
338
                } else {
339
                    $got .= '0';
340
                }
341
            }
342
            $this->assertEquals($answer, $got);
343
        }
344
    }
345
346
    public function testBase64()
347
    {
348
        $sendString = 'Mary had a little lamb,
349
Whose fleece was white as snow,
350
And everywhere that Mary went
351
the lamb was sure to go.
352
353
Mary had a little lamb
354
She tied it to a pylon
355
Ten thousand volts went down its back
356
And turned it into nylon';
357
        $m = new xmlrpcmsg('examples.decode64', array(
358
            new xmlrpcval($sendString, 'base64'),
359
        ));
360
        $v = $this->send($m);
361
        if ($v) {
362
            if (strlen($sendString) == strlen($v->scalarval())) {
363
                $this->assertEquals($sendString, $v->scalarval());
364
            } else {
365
                $this->assertEquals(str_replace(array("\r\n", "\r"), array("\n", "\n"), $sendString), $v->scalarval());
366
            }
367
        }
368
    }
369
370
    public function testCountEntities()
371
    {
372
        $sendString = "h'fd>onc>>l>>rw&bpu>q>e<v&gxs<ytjzkami<";
373
        $m = new xmlrpcmsg('validator1.countTheEntities', array(
374
            new xmlrpcval($sendString, 'string'),
375
        ));
376
        $v = $this->send($m);
377
        if ($v) {
378
            $got = '';
379
            $expected = '37210';
380
            $expect_array = array('ctLeftAngleBrackets', 'ctRightAngleBrackets', 'ctAmpersands', 'ctApostrophes', 'ctQuotes');
381
            foreach($expect_array as $val) {
382
                $b = $v->structmem($val);
0 ignored issues
show
Deprecated Code introduced by
The function PhpXmlRpc\Value::structMem() has been deprecated: use array access, e.g. $val[$key] ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

382
                $b = /** @scrutinizer ignore-deprecated */ $v->structmem($val);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
Bug introduced by
The method structmem() does not exist on PhpXmlRpc\Response. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

382
                /** @scrutinizer ignore-call */ 
383
                $b = $v->structmem($val);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
383
                $got .= $b->scalarVal();
384
            }
385
            $this->assertEquals($expected, $got);
386
        }
387
    }
388
389
    protected function _multicall_msg($method, $params)
390
    {
391
        $struct = array();
392
        $struct['methodName'] = new xmlrpcval($method, 'string');
393
        $struct['params'] = new xmlrpcval($params, 'array');
394
395
        return new xmlrpcval($struct, 'struct');
396
    }
397
398
    public function testServerMulticall()
399
    {
400
        // We manually construct a system.multicall() call to ensure
401
        // that the server supports it.
402
403
        // NB: This test will NOT pass if server does not support system.multicall.
404
405
        // Based on http://xmlrpc-c.sourceforge.net/hacks/test_multicall.py
406
        $good1 = $this->_multicall_msg(
407
            'system.methodHelp',
408
            array(php_xmlrpc_encode('system.listMethods')));
409
        $bad = $this->_multicall_msg(
410
            'test.nosuch',
411
            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
412
        $recursive = $this->_multicall_msg(
413
            'system.multicall',
414
            array(new xmlrpcval(array(), 'array')));
415
        $good2 = $this->_multicall_msg(
416
            'system.methodSignature',
417
            array(php_xmlrpc_encode('system.listMethods')));
418
        $arg = new xmlrpcval(
419
            array($good1, $bad, $recursive, $good2),
420
            'array'
421
        );
422
423
        $m = new xmlrpcmsg('system.multicall', array($arg));
424
        $v = $this->send($m);
425
        if ($v) {
426
            //$this->assertEquals(0, $r->faultCode(), "fault from system.multicall");
427
            $this->assertEquals(4, $v->arraysize(), "bad number of return values");
0 ignored issues
show
Deprecated Code introduced by
The function PhpXmlRpc\Value::arraySize() has been deprecated: use count() instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

427
            $this->assertEquals(4, /** @scrutinizer ignore-deprecated */ $v->arraysize(), "bad number of return values");

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
428
429
            $r1 = $v->arraymem(0);
0 ignored issues
show
Deprecated Code introduced by
The function PhpXmlRpc\Value::arrayMem() has been deprecated: use array access, e.g. $val[$key] ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

429
            $r1 = /** @scrutinizer ignore-deprecated */ $v->arraymem(0);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
430
            $this->assertTrue(
431
                $r1->kindOf() == 'array' && $r1->arraysize() == 1,
0 ignored issues
show
Deprecated Code introduced by
The function PhpXmlRpc\Value::arraySize() has been deprecated: use count() instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

431
                $r1->kindOf() == 'array' && /** @scrutinizer ignore-deprecated */ $r1->arraysize() == 1,

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
432
                "did not get array of size 1 from good1"
433
            );
434
435
            $r2 = $v->arraymem(1);
0 ignored issues
show
Deprecated Code introduced by
The function PhpXmlRpc\Value::arrayMem() has been deprecated: use array access, e.g. $val[$key] ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

435
            $r2 = /** @scrutinizer ignore-deprecated */ $v->arraymem(1);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
436
            $this->assertEquals('struct', $r2->kindOf(), "no fault from bad");
437
438
            $r3 = $v->arraymem(2);
0 ignored issues
show
Deprecated Code introduced by
The function PhpXmlRpc\Value::arrayMem() has been deprecated: use array access, e.g. $val[$key] ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

438
            $r3 = /** @scrutinizer ignore-deprecated */ $v->arraymem(2);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
439
            $this->assertEquals('struct', $r3->kindOf(), "recursive system.multicall did not fail");
440
441
            $r4 = $v->arraymem(3);
0 ignored issues
show
Deprecated Code introduced by
The function PhpXmlRpc\Value::arrayMem() has been deprecated: use array access, e.g. $val[$key] ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

441
            $r4 = /** @scrutinizer ignore-deprecated */ $v->arraymem(3);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
442
            $this->assertTrue(
443
                $r4->kindOf() == 'array' && $r4->arraysize() == 1,
0 ignored issues
show
Deprecated Code introduced by
The function PhpXmlRpc\Value::arraySize() has been deprecated: use count() instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

443
                $r4->kindOf() == 'array' && /** @scrutinizer ignore-deprecated */ $r4->arraysize() == 1,

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
444
                "did not get array of size 1 from good2"
445
            );
446
        }
447
    }
448
449
    public function testClientMulticall1()
450
    {
451
        // NB: This test will NOT pass if server does not support system.multicall.
452
453
        $noMultiCall = $this->client->no_multicall;
0 ignored issues
show
Bug Best Practice introduced by
The property $no_multicall is declared protected in PhpXmlRpc\Client. Since you implement __get, consider adding a @property or @property-read.
Loading history...
454
        $this->client->no_multicall = false;
455
456
        $good1 = new xmlrpcmsg('system.methodHelp',
457
            array(php_xmlrpc_encode('system.listMethods')));
458
        $bad = new xmlrpcmsg('test.nosuch',
459
            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
460
        $recursive = new xmlrpcmsg('system.multicall',
461
            array(new xmlrpcval(array(), 'array')));
462
        $good2 = new xmlrpcmsg('system.methodSignature',
463
            array(php_xmlrpc_encode('system.listMethods'))
464
        );
465
466
        $r = $this->send(array($good1, $bad, $recursive, $good2));
467
        if ($r) {
468
            $this->assertEquals(4, count($r), "wrong number of return values");
469
        }
470
471
        $this->assertEquals(0, $r[0]->faultCode(), "fault from good1");
472
        if (!$r[0]->faultCode()) {
473
            $val = $r[0]->value();
474
            $this->assertTrue(
475
                $val->kindOf() == 'scalar' && $val->scalartyp() == 'string',
476
                "good1 did not return string"
477
            );
478
        }
479
        $this->assertNotEquals(0, $r[1]->faultCode(), "no fault from bad");
480
        $this->assertNotEquals(0, $r[2]->faultCode(), "no fault from recursive system.multicall");
481
        $this->assertEquals(0, $r[3]->faultCode(), "fault from good2");
482
        if (!$r[3]->faultCode()) {
483
            $val = $r[3]->value();
484
            $this->assertEquals('array', $val->kindOf(), "good2 did not return array");
485
        }
486
        // This is the only assert in this test which should fail
487
        // if the test server does not support system.multicall.
488
        $this->assertEquals(false, $this->client->no_multicall, "server does not support system.multicall");
489
490
        $this->client->no_multicall = $noMultiCall;
491
    }
492
493
    public function testClientMulticall2()
494
    {
495
        // NB: This test will NOT pass if server does not support system.multicall.
496
497
        $noMultiCall = $this->client->no_multicall;
0 ignored issues
show
Bug Best Practice introduced by
The property $no_multicall is declared protected in PhpXmlRpc\Client. Since you implement __get, consider adding a @property or @property-read.
Loading history...
498
        $this->client->no_multicall = true;
499
500
        $good1 = new xmlrpcmsg('system.methodHelp',
501
            array(php_xmlrpc_encode('system.listMethods')));
502
        $bad = new xmlrpcmsg('test.nosuch',
503
            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
504
        $recursive = new xmlrpcmsg('system.multicall',
505
            array(new xmlrpcval(array(), 'array')));
506
        $good2 = new xmlrpcmsg('system.methodSignature',
507
            array(php_xmlrpc_encode('system.listMethods'))
508
        );
509
510
        $r = $this->send(array($good1, $bad, $recursive, $good2));
511
        if ($r) {
512
            $this->assertEquals(4, count($r), "wrong number of return values");
513
        }
514
515
        $this->assertEquals(0, $r[0]->faultCode(), "fault from good1");
516
        if (!$r[0]->faultCode()) {
517
            $val = $r[0]->value();
518
            $this->assertTrue(
519
                $val->kindOf() == 'scalar' && $val->scalartyp() == 'string',
520
                "good1 did not return string");
521
        }
522
        $this->assertNotEquals(0, $r[1]->faultCode(), "no fault from bad");
523
        $this->assertEquals(0, $r[2]->faultCode(), "fault from (non recursive) system.multicall");
524
        $this->assertEquals(0, $r[3]->faultCode(), "fault from good2");
525
        if (!$r[3]->faultCode()) {
526
            $val = $r[3]->value();
527
            $this->assertEquals('array', $val->kindOf(), "good2 did not return array");
528
        }
529
530
        $this->client->no_multicall = $noMultiCall;
531
    }
532
533
    public function testClientMulticall3()
534
    {
535
        // NB: This test will NOT pass if server does not support system.multicall.
536
537
        $noMultiCall = $this->client->no_multicall;
0 ignored issues
show
Bug Best Practice introduced by
The property $no_multicall is declared protected in PhpXmlRpc\Client. Since you implement __get, consider adding a @property or @property-read.
Loading history...
538
        $returnType = $this->client->return_type;
0 ignored issues
show
Bug Best Practice introduced by
The property $return_type is declared protected in PhpXmlRpc\Client. Since you implement __get, consider adding a @property or @property-read.
Loading history...
539
540
        $this->client->return_type = 'phpvals';
541
        $this->client->no_multicall = false;
542
543
        $good1 = new xmlrpcmsg('system.methodHelp',
544
            array(php_xmlrpc_encode('system.listMethods')));
545
        $bad = new xmlrpcmsg('test.nosuch',
546
            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
547
        $recursive = new xmlrpcmsg('system.multicall',
548
            array(new xmlrpcval(array(), 'array')));
549
        $good2 = new xmlrpcmsg('system.methodSignature',
550
            array(php_xmlrpc_encode('system.listMethods'))
551
        );
552
553
        $r = $this->send(array($good1, $bad, $recursive, $good2));
554
        if ($r) {
555
            $this->assertEquals(4, count($r), "wrong number of return values");
556
        }
557
        $this->assertEquals(0, $r[0]->faultCode(), "fault from good1");
558
        if (!$r[0]->faultCode()) {
559
            $val = $r[0]->value();
560
            $this->assertIsString($val, "good1 did not return string");
561
        }
562
        $this->assertNotEquals(0, $r[1]->faultCode(), "no fault from bad");
563
        $this->assertNotEquals(0, $r[2]->faultCode(), "no fault from recursive system.multicall");
564
        $this->assertEquals(0, $r[3]->faultCode(), "fault from good2");
565
        if (!$r[3]->faultCode()) {
566
            $val = $r[3]->value();
567
            $this->assertIsArray($val, "good2 did not return array");
568
        }
569
570
        $this->client->return_type = $returnType;
571
        $this->client->no_multicall = $noMultiCall;
572
    }
573
574
    public function testClientMulticall4()
575
    {
576
        // NB: This test will NOT pass if server does not support system.multicall.
577
578
        $noMultiCall = $this->client->no_multicall;
0 ignored issues
show
Bug Best Practice introduced by
The property $no_multicall is declared protected in PhpXmlRpc\Client. Since you implement __get, consider adding a @property or @property-read.
Loading history...
579
        $returnType = $this->client->return_type;
0 ignored issues
show
Bug Best Practice introduced by
The property $return_type is declared protected in PhpXmlRpc\Client. Since you implement __get, consider adding a @property or @property-read.
Loading history...
580
581
        $this->client->return_type = 'xml';
582
        $this->client->no_multicall = false;
583
584
        $good1 = new xmlrpcmsg('system.methodHelp',
585
            array(php_xmlrpc_encode('system.listMethods')));
586
        $good2 = new xmlrpcmsg('system.methodSignature',
587
            array(php_xmlrpc_encode('system.listMethods'))
588
        );
589
590
        $r = $this->send(array($good1, $good2));
591
        if ($r) {
592
            $this->assertEquals(2, count($r), "wrong number of return values");
593
        }
594
        $this->assertEquals(0, $r[0]->faultCode(), "fault from good1");
595
        $this->assertEquals(0, $r[1]->faultCode(), "fault from good2");
596
597
        $hr = $r[0]->httpResponse();
598
        $this->assertEquals(200, $hr['status_code'], "http response of multicall has no status code");
599
        $this->assertEquals($r[0]->httpResponse(), $r[1]->httpResponse(), "http response of multicall items differs");
600
601
        $this->client->return_type = $returnType;
602
        $this->client->no_multicall = $noMultiCall;
603
    }
604
605
    public function testCatchWarnings()
606
    {
607
        $m = new xmlrpcmsg('tests.generatePHPWarning', array(
608
            new xmlrpcval('whatever', 'string'),
609
        ));
610
        $this->addQueryParams(array('FORCE_DEBUG' => 0));
611
        $v = $this->send($m);
612
        if ($v) {
613
            $this->assertEquals(true, $v->scalarval());
614
        }
615
    }
616
617
    public function testCatchExceptions()
618
    {
619
        // this tests for the server to catch exceptions with error code 0
620
        $m = new xmlrpcmsg('tests.raiseException', array(
621
            new xmlrpcval(0, 'int'),
622
        ));
623
        $v = $this->send($m, $GLOBALS['xmlrpcerr']['server_error']);
0 ignored issues
show
Unused Code introduced by
The assignment to $v is dead and can be removed.
Loading history...
624
625
        // these test for the different server exception catching modes
626
        $m = new xmlrpcmsg('tests.raiseException', array(
627
            new xmlrpcval(3, 'int'),
628
        ));
629
        $v = $this->send($m, $GLOBALS['xmlrpcerr']['server_error']);
630
        $this->addQueryParams(array('EXCEPTION_HANDLING' => 1));
631
        $v = $this->send($m, 3); // the error code of the expected exception
632
        $this->addQueryParams(array('EXCEPTION_HANDLING' => 2));
633
        // depending on whether display_errors is ON or OFF on the server, we will get back a different error here,
634
        // as php will generate an http status code of either 200 or 500...
635
        $v = $this->send($m, array($GLOBALS['xmlrpcerr']['invalid_return'], $GLOBALS['xmlrpcerr']['http_error']));
636
    }
637
638
    public function testCatchErrors()
639
    {
640
        if (version_compare(PHP_VERSION, '7.0.0', '<'))
641
        {
642
            $this->markTestSkipped('Cannot test php Error on php < 7.0');
643
        }
644
645
        // these test for the different server error catching modes
646
        $m = new xmlrpcmsg('tests.raiseError');
647
        $v = $this->send($m, $GLOBALS['xmlrpcerr']['server_error']);
0 ignored issues
show
Unused Code introduced by
The assignment to $v is dead and can be removed.
Loading history...
648
        $this->addQueryParams(array('EXCEPTION_HANDLING' => 1));
649
        $v = $this->send($m, 1); // the error code of the expected exception
650
        $this->addQueryParams(array('EXCEPTION_HANDLING' => 2));
651
        // depending on whether display_errors is ON or OFF on the server, we will get back a different error here,
652
        // as php will generate an http status code of either 200 or 500...
653
        $v = $this->send($m, array($GLOBALS['xmlrpcerr']['invalid_return'], $GLOBALS['xmlrpcerr']['http_error']));
654
    }
655
656
    public function testZeroParams()
657
    {
658
        $m = new xmlrpcmsg('system.listMethods');
659
        $v = $this->send($m);
0 ignored issues
show
Unused Code introduced by
The assignment to $v is dead and can be removed.
Loading history...
660
    }
661
662
    public function testNullParams()
663
    {
664
        $m = new xmlrpcmsg('tests.getStateName.12', array(
665
            new xmlrpcval('whatever', 'null'),
666
            new xmlrpcval(23, 'int'),
667
        ));
668
        $v = $this->send($m);
669
        if ($v) {
670
            $this->assertEquals('Michigan', $v->scalarval());
671
        }
672
        $m = new xmlrpcmsg('tests.getStateName.12', array(
673
            new xmlrpcval(23, 'int'),
674
            new xmlrpcval('whatever', 'null'),
675
        ));
676
        $v = $this->send($m);
677
        if ($v) {
678
            $this->assertEquals('Michigan', $v->scalarval());
679
        }
680
        $m = new xmlrpcmsg('tests.getStateName.12', array(
681
            new xmlrpcval(23, 'int')
682
        ));
683
        $v = $this->send($m, array($GLOBALS['xmlrpcerr']['incorrect_params']));
0 ignored issues
show
Unused Code introduced by
The assignment to $v is dead and can be removed.
Loading history...
684
    }
685
686
    public function testCodeInjectionServerSide()
687
    {
688
        $m = new xmlrpcmsg('system.MethodHelp');
689
        $m->payload = "<?xml version=\"1.0\"?><methodCall><methodName>validator1.echoStructTest</methodName><params><param><value><struct><member><name>','')); echo('gotcha!'); die(); //</name></member></struct></value></param></params></methodCall>";
690
        $v = $this->send($m);
691
        if ($v) {
692
            $this->assertEquals(0, $v->structsize());
0 ignored issues
show
Deprecated Code introduced by
The function PhpXmlRpc\Value::structSize() has been deprecated: use count() instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

692
            $this->assertEquals(0, /** @scrutinizer ignore-deprecated */ $v->structsize());

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
Bug introduced by
The method structsize() does not exist on PhpXmlRpc\Response. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

692
            $this->assertEquals(0, $v->/** @scrutinizer ignore-call */ structsize());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
693
        }
694
    }
695
696
    public function testServerWrappedFunction()
697
    {
698
        $m = new xmlrpcmsg('tests.getStateName.2', array(
699
            new xmlrpcval(23, 'int'),
700
        ));
701
        $v = $this->send($m);
702
        $this->assertEquals('Michigan', $v->scalarval());
703
704
        // this generates an exception in the function which was wrapped, which is by default wrapped in a known error response
705
        $m = new xmlrpcmsg('tests.getStateName.2', array(
706
            new xmlrpcval(0, 'int'),
707
        ));
708
        $v = $this->send($m, $GLOBALS['xmlrpcerr']['server_error']);
0 ignored issues
show
Unused Code introduced by
The assignment to $v is dead and can be removed.
Loading history...
709
710
        // check if the generated function dispatch map is fine, by checking if the server registered it
711
        $m = new xmlrpcmsg('system.methodSignature', array(
712
            new xmlrpcval('tests.getStateName.2'),
713
        ));
714
        $v = $this->send($m);
715
        $encoder = new \PhpXmlRpc\Encoder();
716
        $this->assertEquals(array(array('string', 'int')), $encoder->decode($v));
717
    }
718
719
    public function testServerWrappedFunctionAsSource()
720
    {
721
        $m = new xmlrpcmsg('tests.getStateName.6', array(
722
            new xmlrpcval(23, 'int'),
723
        ));
724
        $v = $this->send($m);
725
        $this->assertEquals('Michigan', $v->scalarval());
726
727
        // this generates an exception in the function which was wrapped, which is by default wrapped in a known error response
728
        $m = new xmlrpcmsg('tests.getStateName.6', array(
729
            new xmlrpcval(0, 'int'),
730
        ));
731
        $v = $this->send($m, $GLOBALS['xmlrpcerr']['server_error']);
0 ignored issues
show
Unused Code introduced by
The assignment to $v is dead and can be removed.
Loading history...
732
    }
733
734
    public function testServerWrappedObjectMethods()
735
    {
736
        $m = new xmlrpcmsg('tests.getStateName.3', array(
737
            new xmlrpcval(23, 'int'),
738
        ));
739
        $v = $this->send($m);
740
        $this->assertEquals('Michigan', $v->scalarval());
741
742
        $m = new xmlrpcmsg('tests.getStateName.4', array(
743
            new xmlrpcval(23, 'int'),
744
        ));
745
        $v = $this->send($m);
746
        $this->assertEquals('Michigan', $v->scalarval());
747
748
        $m = new xmlrpcmsg('tests.getStateName.5', array(
749
            new xmlrpcval(23, 'int'),
750
        ));
751
        $v = $this->send($m);
752
        $this->assertEquals('Michigan', $v->scalarval());
753
754
        $m = new xmlrpcmsg('tests.getStateName.7', array(
755
            new xmlrpcval(23, 'int'),
756
        ));
757
        $v = $this->send($m);
758
        $this->assertEquals('Michigan', $v->scalarval());
759
760
        $m = new xmlrpcmsg('tests.getStateName.8', array(
761
            new xmlrpcval(23, 'int'),
762
        ));
763
        $v = $this->send($m);
764
        $this->assertEquals('Michigan', $v->scalarval());
765
766
        $m = new xmlrpcmsg('tests.getStateName.9', array(
767
            new xmlrpcval(23, 'int'),
768
        ));
769
        $v = $this->send($m);
770
        $this->assertEquals('Michigan', $v->scalarval());
771
    }
772
773
    public function testServerWrappedObjectMethodsAsSource()
774
    {
775
        $m = new xmlrpcmsg('tests.getStateName.7', array(
776
            new xmlrpcval(23, 'int'),
777
        ));
778
        $v = $this->send($m);
779
        $this->assertEquals('Michigan', $v->scalarval());
780
781
        $m = new xmlrpcmsg('tests.getStateName.8', array(
782
            new xmlrpcval(23, 'int'),
783
        ));
784
        $v = $this->send($m);
785
        $this->assertEquals('Michigan', $v->scalarval());
786
787
        $m = new xmlrpcmsg('tests.getStateName.9', array(
788
            new xmlrpcval(23, 'int'),
789
        ));
790
        $v = $this->send($m);
791
        $this->assertEquals('Michigan', $v->scalarval());
792
    }
793
794
    public function testServerClosure()
795
    {
796
        $m = new xmlrpcmsg('tests.getStateName.10', array(
797
            new xmlrpcval(23, 'int'),
798
        ));
799
        $v = $this->send($m);
800
        $this->assertEquals('Michigan', $v->scalarval());
801
    }
802
803
    public function testServerWrappedClosure()
804
    {
805
        $m = new xmlrpcmsg('tests.getStateName.11', array(
806
            new xmlrpcval(23, 'int'),
807
        ));
808
        $v = $this->send($m);
809
        $this->assertEquals('Michigan', $v->scalarval());
810
    }
811
812
    public function testServerWrappedClass()
813
    {
814
        $m = new xmlrpcmsg('tests.handlersContainer.findState', array(
815
            new xmlrpcval(23, 'int'),
816
        ));
817
        $v = $this->send($m);
818
        $this->assertEquals('Michigan', $v->scalarval());
819
    }
820
821
    public function testServerWrappedClassWithNamespace()
822
    {
823
        $m = new xmlrpcmsg('namespacetest.findState', array(
824
            new xmlrpcval(23, 'int'),
825
        ));
826
        $v = $this->send($m);
827
        $this->assertEquals('Michigan', $v->scalarval());
828
    }
829
830
    public function testWrapInexistentMethod()
831
    {
832
        // make a 'deep client copy' as the original one might have many properties set
833
        $func = wrap_xmlrpc_method($this->client, 'examples.getStateName.notexisting', array('simple_client_copy' => 0));
834
        $this->assertEquals(false, $func);
835
    }
836
837
    public function testWrapInexistentUrl()
838
    {
839
        $this->client->path = '/notexisting';
840
        // make a 'deep client copy' as the original one might have many properties set
841
        $func = wrap_xmlrpc_method($this->client, 'examples.getStateName', array('simple_client_copy' => 0));
842
        $this->assertEquals(false, $func);
843
    }
844
845
    public function testWrappedMethod()
846
    {
847
        // make a 'deep client copy' as the original one might have many properties set
848
        $func = wrap_xmlrpc_method($this->client, 'examples.getStateName', array('simple_client_copy' => 0));
849
        if ($func == false) {
850
            $this->fail('Registration of examples.getStateName failed');
851
        } else {
852
            $v = $func(23);
853
            // work around bug in current (or old?) version of phpunit when reporting the error
854
            /*if (is_object($v)) {
855
                $v = var_export($v, true);
856
            }*/
857
            $this->assertEquals('Michigan', $v);
858
        }
859
    }
860
861
    public function testWrappedMethodAsSource()
862
    {
863
        // make a 'deep client copy' as the original one might have many properties set
864
        $func = wrap_xmlrpc_method($this->client, 'examples.getStateName', array('simple_client_copy' => 0, 'return_source' => true));
865
        if ($func == false) {
866
            $this->fail('Registration of examples.getStateName failed');
867
        } else {
868
            eval($func['source']);
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
869
            $func = $func['function'];
870
            $v = $func(23);
871
            // work around bug in current (or old?) version of phpunit when reporting the error
872
            /*if (is_object($v)) {
873
                $v = var_export($v, true);
874
            }*/
875
            $this->assertEquals('Michigan', $v);
876
        }
877
    }
878
879
    public function testWrappedClass()
880
    {
881
        // make a 'deep client copy' as the original one might have many properties set
882
        // also for speed only wrap one method of the whole server
883
        $class = wrap_xmlrpc_server($this->client, array('simple_client_copy' => 0, 'method_filter' => '/examples\.getStateName/' ));
884
        if ($class == '') {
885
            $this->fail('Registration of remote server failed');
886
        } else {
887
            $obj = new $class();
888
            if (!is_callable(array($obj, 'examples_getStateName'))) {
889
                $this->fail('Registration of remote server failed to import method "examples_getStateName"');
890
            } else {
891
                $v = $obj->examples_getStateName(23);
892
                // work around bug in current (or old?) version of phpunit when reporting the error
893
                /*if (is_object($v)) {
894
                    $v = var_export($v, true);
895
                }*/
896
                $this->assertEquals('Michigan', $v);
897
            }
898
        }
899
    }
900
901
    public function testTransferOfObjectViaWrapping()
902
    {
903
        // make a 'deep client copy' as the original one might have many properties set
904
        $func = wrap_xmlrpc_method($this->client, 'tests.returnPhpObject', array('simple_client_copy' => 0,
905
            'decode_php_objs' => true));
906
        if ($func == false) {
907
            $this->fail('Registration of tests.returnPhpObject failed');
908
        } else {
909
            $v = $func();
910
            $obj = new stdClass();
911
            $obj->hello = 'world';
912
            $this->assertEquals($obj, $v);
913
        }
914
    }
915
916
    public function testGetCookies()
917
    {
918
        // let server set to us some cookies we tell it
919
        $cookies = array(
920
            //'c1' => array(),
921
            'c2' => array('value' => 'c2'),
922
            'c3' => array('value' => 'c3', 'expires' => time() + 60 * 60 * 24 * 30),
923
            'c4' => array('value' => 'c4', 'expires' => time() + 60 * 60 * 24 * 30, 'path' => '/'),
924
            'c5' => array('value' => 'c5', 'expires' => time() + 60 * 60 * 24 * 30, 'path' => '/', 'domain' => 'localhost'),
925
        );
926
        $cookiesval = php_xmlrpc_encode($cookies);
927
        $m = new xmlrpcmsg('tests.setcookies', array($cookiesval));
928
        $r = $this->send($m, 0, true);
929
        if ($r) {
930
            $v = $r->value();
931
            $this->assertEquals(1, $v->scalarval());
932
            // now check if we decoded the cookies as we had set them
933
            $rcookies = $r->cookies();
934
            // remove extra cookies which might have been set by proxies
935
            foreach ($rcookies as $c => $v) {
936
                if (!in_array($c, array('c2', 'c3', 'c4', 'c5'))) {
937
                    unset($rcookies[$c]);
938
                }
939
                // Seems like we get this when using php-fpm and php 5.5+ ...
940
                if (isset($rcookies[$c]['Max-Age'])) {
941
                    unset($rcookies[$c]['Max-Age']);
942
                }
943
            }
944
            foreach ($cookies as $c => $v) {
945
                // format for date string in cookies: 'Mon, 31 Oct 2005 13:50:56 GMT'
946
                // but PHP versions differ on that, some use 'Mon, 31-Oct-2005 13:50:56 GMT'...
947
                if (isset($v['expires'])) {
948
                    if (isset($rcookies[$c]['expires']) && strpos($rcookies[$c]['expires'], '-')) {
949
                        $cookies[$c]['expires'] = gmdate('D, d\-M\-Y H:i:s \G\M\T', $cookies[$c]['expires']);
950
                    } else {
951
                        $cookies[$c]['expires'] = gmdate('D, d M Y H:i:s \G\M\T', $cookies[$c]['expires']);
952
                    }
953
                }
954
            }
955
956
            $this->assertEquals($cookies, $rcookies);
957
        }
958
    }
959
960
    public function testSetCookies()
961
    {
962
        // let server set to us some cookies we tell it
963
        $cookies = array(
964
            'c0' => null,
965
            'c1' => 1,
966
            'c2' => '2 3',
967
            'c3' => '!@#$%^&*()_+|}{":?><,./\';[]\\=-',
968
        );
969
        $m = new xmlrpcmsg('tests.getcookies', array());
970
        foreach ($cookies as $cookie => $val) {
971
            $this->client->setCookie($cookie, $val);
972
            $cookies[$cookie] = (string)$cookies[$cookie];
973
        }
974
        $r = $this->client->send($m, $this->timeout, $this->method);
975
        $this->assertEquals(0, $r->faultCode(), 'Error ' . $r->faultCode() . ' connecting to server: ' . $r->faultString());
976
        if (!$r->faultCode()) {
977
            $v = $r->value();
978
            $v = php_xmlrpc_decode($v);
979
980
            // take care of the extra cookies used for coverage collection and test mechanics
981
            if (isset($v['PHPUNIT_SELENIUM_TEST_ID'])) {
982
                unset($v['PHPUNIT_SELENIUM_TEST_ID']);
983
            }
984
            if (isset($v['PHPUNIT_RANDOM_TEST_ID'])) {
985
                unset($v['PHPUNIT_RANDOM_TEST_ID']);
986
            }
987
988
            // on IIS and Apache getallheaders returns something slightly different...
989
            $this->assertEquals($cookies, $v);
990
        }
991
    }
992
993
    public function testServerComments()
994
    {
995
        $m = new xmlrpcmsg('tests.handlersContainer.debugMessageGenerator', array(
996
            new xmlrpcval('hello world', 'string'),
997
        ));
998
        $r = $this->send($m, 0, true);
999
        $this->assertStringContainsString('hello world', $r->raw_data);
1000
    }
1001
1002
    public function testSendTwiceSameMsg()
1003
    {
1004
        $m = new xmlrpcmsg('examples.stringecho', array(
1005
            new xmlrpcval('hello world', 'string'),
1006
        ));
1007
        $v1 = $this->send($m);
1008
        $v2 = $this->send($m);
1009
        if ($v1 && $v2) {
1010
            $this->assertEquals($v1, $v2);
1011
        }
1012
    }
1013
1014
    public function testNegativeDebug()
1015
    {
1016
        $m = new xmlrpcmsg('examples.stringecho', array(
1017
            new xmlrpcval('hello world', 'string'),
1018
        ));
1019
        $v1 = $this->send($m, 0, true);
1020
        $h = $v1->httpResponse();
1021
        $this->assertEquals('200', $h['status_code']);
1022
        $this->assertNotEmpty($h['headers']);
1023
1024
        $d = $this->client->getOption('debug');
1025
        $this->client->setDebug(-1);
1026
        $v2 = $this->send($m, 0, true);
1027
        $this->client->setDebug($d);
1028
        $h = $v2->httpResponse();
1029
        $this->assertEmpty($h['headers']);
1030
        $this->assertEmpty($h['raw_data']);
1031
    }
1032
}
1033