Passed
Push — master ( 02b7f4...c1cbf5 )
by Gaetano
07:18
created

ServerTest::_run()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 26
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 12
c 0
b 0
f 0
nc 4
nop 1
dl 0
loc 26
rs 9.8666
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
23
    /**
24
     * @todo instead of overriding fail via _fail, implement Yoast\PHPUnitPolyfills\TestListeners\TestListenerDefaultImplementation
25
     */
26
    public static function _fail($message = '')
27
    {
28
        // save in a static var that this particular test has failed
29
        // (but only if not called from subclass objects / multitests)
30
        if (function_exists('debug_backtrace') && strtolower(get_called_class()) == 'localhosttests') {
31
            $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
32
            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...
33
                if (strpos($trace[$i]['function'], 'test') === 0) {
34
                    self::$failed_tests[$trace[$i]['function']] = true;
35
                    break;
36
                }
37
            }
38
        }
39
40
        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

40
        parent::/** @scrutinizer ignore-call */ 
41
                _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...
41
    }
42
43
    public function set_up()
44
    {
45
        parent::set_up();
46
47
        $server = explode(':', $this->args['HTTPSERVER']);
48
        if (count($server) > 1) {
49
            $this->client = new xmlrpc_client($this->args['HTTPURI'], $server[0], $server[1]);
0 ignored issues
show
Bug introduced by
$server[1] of type string is incompatible with the type integer expected by parameter $port of xmlrpc_client::__construct(). ( Ignorable by Annotation )

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

49
            $this->client = new xmlrpc_client($this->args['HTTPURI'], $server[0], /** @scrutinizer ignore-type */ $server[1]);
Loading history...
50
        } else {
51
            $this->client = new xmlrpc_client($this->args['HTTPURI'], $this->args['HTTPSERVER']);
52
        }
53
54
        $this->client->setDebug($this->args['DEBUG']);
55
        $this->client->request_compression = $this->request_compression;
56
        $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...
57
    }
58
59
    /**
60
     * @param PhpXmlRpc\Request|array $msg
61
     * @param int|array $errorCode expected error codes
62
     * @param bool $returnResponse
63
     * @return mixed|\PhpXmlRpc\Response|\PhpXmlRpc\Response[]|\PhpXmlRpc\Value|string|null
64
     */
65
    protected function send($msg, $errorCode = 0, $returnResponse = false)
66
    {
67
        if ($this->collectCodeCoverageInformation) {
68
            $this->client->setCookie('PHPUNIT_SELENIUM_TEST_ID', $this->testId);
69
        }
70
71
        $r = $this->client->send($msg, $this->timeout, $this->method);
72
        // for multicall, return directly array of responses
73
        if (is_array($r)) {
74
            return $r;
75
        }
76
        $this->validateResponse($r);
77
        if (is_array($errorCode)) {
78
            $this->assertContains($r->faultCode(), $errorCode, 'Error ' . $r->faultCode() . ' connecting to server: ' . $r->faultString());
79
        } else {
80
            $this->assertEquals($errorCode, $r->faultCode(), 'Error ' . $r->faultCode() . ' connecting to server: ' . $r->faultString());
81
        }
82
        if (!$r->faultCode()) {
83
            if ($returnResponse) {
84
                return $r;
85
            } else {
86
                return $r->value();
87
            }
88
        } else {
89
            return null;
90
        }
91
    }
92
93
    protected function validateResponse($r)
94
    {
95
        // to be implemented in subclasses
96
    }
97
98
    /**
99
     * Adds (and replaces) query params to the url currently used by the client
100
     * @param array $data
101
     */
102
    protected function addQueryParams($data)
103
    {
104
        $query = parse_url($this->client->path, PHP_URL_QUERY);
105
        parse_str($query, $vars);
106
        $query = http_build_query(array_merge($vars, $data));
107
        $this->client->path = parse_url($this->client->path, PHP_URL_PATH) . '?' . $query;
108
    }
109
110
    public function testString()
111
    {
112
        $sendString = "here are 3 \"entities\": < > & " .
113
            "and here's a dollar sign: \$pretendvarname and a backslash too: " . chr(92) .
114
            " - isn't that great? \\\"hackery\\\" at it's best " .
115
            " also don't want to miss out on \$item[0]. " .
116
            "The real weird stuff follows: CRLF here" . chr(13) . chr(10) .
117
            "a simple CR here" . chr(13) .
118
            "a simple LF here" . chr(10) .
119
            "and then LFCR" . chr(10) . chr(13) .
120
            "last but not least weird names: G" . chr(252) . "nter, El" . chr(232) . "ne, and an xml comment closing tag: -->";
121
        $m = new xmlrpcmsg('examples.stringecho', array(
122
            new xmlrpcval($sendString, 'string'),
123
        ));
124
        $v = $this->send($m);
125
        if ($v) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $v of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
126
            // when sending/receiving non-US-ASCII encoded strings, XML says cr-lf can be normalized.
127
            // so we relax our tests...
128
            $l1 = strlen($sendString);
129
            $l2 = strlen($v->scalarval());
0 ignored issues
show
Bug introduced by
The method scalarval() does not exist on integer. ( Ignorable by Annotation )

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

129
            $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...
130
            if ($l1 == $l2) {
131
                $this->assertEquals($sendString, $v->scalarval());
132
            } else {
133
                $this->assertEquals(str_replace(array("\r\n", "\r"), array("\n", "\n"), $sendString), $v->scalarval());
134
            }
135
        }
136
    }
137
138
    public function testLatin1String()
139
    {
140
        $sendString =
141
            "last but not least weird names: G" . chr(252) . "nter, El" . chr(232) . "ne";
142
        $x = '<?xml version="1.0" encoding="ISO-8859-1"?><methodCall><methodName>examples.stringecho</methodName><params><param><value>'.
143
            $sendString.
144
            '</value></param></params></methodCall>';
145
        $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

145
        $v = $this->send(/** @scrutinizer ignore-type */ $x);
Loading history...
146
        if ($v) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $v of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
147
            $this->assertEquals($sendString, $v->scalarval());
148
        }
149
    }
150
151
    public function testExoticCharsetsRequests()
152
    {
153
        // note that we should disable this call also when mbstring is missing server-side
154
        if (!function_exists('mb_convert_encoding')) {
155
            $this->markTestSkipped('Miss mbstring extension to test exotic charsets');
156
            return;
157
        }
158
        $sendString = 'κόσμε'; // Greek word 'kosme'
159
        $str = '<?xml version="1.0" encoding="_ENC_"?>
160
<methodCall>
161
    <methodName>examples.stringecho</methodName>
162
    <params>
163
        <param>
164
        <value><string>'.$sendString.'</string></value>
165
        </param>
166
    </params>
167
</methodCall>';
168
169
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'UTF-8';
170
        // This test is known to fail with old mbstring versions, at least the ones we get with php 5.4, 5.5 as present
171
        // in the CI test vms
172
        if (version_compare(PHP_VERSION, '5.6.0', '>=')) {
173
            // we have to set the encoding declaration either in the http header or xml prolog, as mb_detect_encoding
174
            // (used on the server side) will fail recognizing these 2 charsets
175
            $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

175
            $v = $this->send(/** @scrutinizer ignore-type */ mb_convert_encoding(str_replace('_ENC_', 'UCS-4', $str), 'UCS-4', 'UTF-8'));
Loading history...
176
            $this->assertEquals($sendString, $v->scalarval());
177
        }
178
        $v = $this->send(mb_convert_encoding(str_replace('_ENC_', 'UTF-16', $str), 'UTF-16', 'UTF-8'));
179
        $this->assertEquals($sendString, $v->scalarval());
180
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
181
    }
182
183
    public function testExoticCharsetsRequests2()
184
    {
185
        // note that we should disable this call also when mbstring is missing server-side
186
        if (!function_exists('mb_convert_encoding')) {
187
            $this->markTestSkipped('Miss mbstring extension to test exotic charsets');
188
            return;
189
        }
190
        $sendString = '安室奈美恵'; // Japanese name "Namie Amuro"
191
        $str = '<?xml version="1.0"?>
192
<methodCall>
193
    <methodName>examples.stringecho</methodName>
194
    <params>
195
        <param>
196
        <value><string>'.$sendString.'</string></value>
197
        </param>
198
    </params>
199
</methodCall>';
200
201
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'UTF-8';
202
        // no encoding declaration either in the http header or xml prolog, let mb_detect_encoding
203
        // (used on the server side) sort it out
204
        $this->addQueryParams(array('DETECT_ENCODINGS' => array('EUC-JP', 'UTF-8')));
205
        $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

205
        $v = $this->send(/** @scrutinizer ignore-type */ mb_convert_encoding($str, 'EUC-JP', 'UTF-8'));
Loading history...
206
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
207
        $this->assertEquals($sendString, $v->scalarval());
208
    }
209
210
    public function testExoticCharsetsRequests3()
211
    {
212
        // note that we should disable this call also when mbstring is missing server-side
213
        if (!function_exists('mb_convert_encoding')) {
214
            $this->markTestSkipped('Miss mbstring extension to test exotic charsets');
215
            return;
216
        }
217
        // the warning suppression is due to utf8_decode being deprecated in php 8.2
218
        $sendString = @utf8_decode('élève');
219
        $str = '<?xml version="1.0"?>
220
<methodCall>
221
    <methodName>examples.stringecho</methodName>
222
    <params>
223
        <param>
224
        <value><string>'.$sendString.'</string></value>
225
        </param>
226
    </params>
227
</methodCall>';
228
229
        // no encoding declaration either in the http header or xml prolog, let mb_detect_encoding
230
        // (used on the server side) sort it out
231
        $this->addQueryParams(array('DETECT_ENCODINGS' => array('ISO-8859-1', 'UTF-8')));
232
        $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

232
        $v = $this->send(/** @scrutinizer ignore-type */ $str);
Loading history...
233
        $this->assertEquals($sendString, $v->scalarval());
234
    }
235
236
    /*public function testLatin1Method()
237
    {
238
        $f = new xmlrpcmsg("tests.iso88591methodname." . chr(224) . chr(252) . chr(232), array(
239
            new xmlrpcval('hello')
240
        ));
241
        $v = $this->send($f);
242
        if ($v) {
243
            $this->assertEquals('hello', $v->scalarval());
244
        }
245
    }*/
246
247
    public function testUtf8Method()
248
    {
249
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'UTF-8';
250
        $m = new xmlrpcmsg("tests.utf8methodname." . 'κόσμε', array(
251
            new xmlrpcval('hello')
252
        ));
253
        $v = $this->send($m);
254
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
255
        if ($v) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $v of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
256
            $this->assertEquals('hello', $v->scalarval());
257
        }
258
    }
259
260
    public function testAddingDoubles()
261
    {
262
        // note that rounding errors mean we keep precision to sensible levels here ;-)
263
        $a = 12.13;
264
        $b = -23.98;
265
        $m = new xmlrpcmsg('examples.addtwodouble', array(
266
            new xmlrpcval($a, 'double'),
267
            new xmlrpcval($b, 'double'),
268
        ));
269
        $v = $this->send($m);
270
        if ($v) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $v of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
271
            $this->assertEquals($a + $b, $v->scalarval());
272
        }
273
    }
274
275
    public function testAdding()
276
    {
277
        $m = new xmlrpcmsg('examples.addtwo', array(
278
            new xmlrpcval(12, 'int'),
279
            new xmlrpcval(-23, 'int'),
280
        ));
281
        $v = $this->send($m);
282
        if ($v) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $v of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
283
            $this->assertEquals(12 - 23, $v->scalarval());
284
        }
285
    }
286
287
    public function testInvalidNumber()
288
    {
289
        $m = new xmlrpcmsg('examples.addtwo', array(
290
            new xmlrpcval('fred', 'int'),
291
            new xmlrpcval("\"; exec('ls')", 'int'),
292
        ));
293
        $v = $this->send($m);
294
        /// @todo a specific fault should be generated here by the server, which we can check
295
        if ($v) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $v of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
296
            $this->assertEquals(0, $v->scalarval());
297
        }
298
    }
299
300
    public function testUnknownMethod()
301
    {
302
        $m = new xmlrpcmsg('examples.a_very_unlikely.method', array());
303
        $v = $this->send($m, \PhpXmlRpc\PhpXmlRpc::$xmlrpcerr['unknown_method']);
0 ignored issues
show
Unused Code introduced by
The assignment to $v is dead and can be removed.
Loading history...
304
    }
305
306
    public function testBoolean()
307
    {
308
        $m = new xmlrpcmsg('examples.invertBooleans', array(
309
            new xmlrpcval(array(
310
                new xmlrpcval(true, 'boolean'),
311
                new xmlrpcval(false, 'boolean'),
312
                new xmlrpcval(1, 'boolean'),
313
                new xmlrpcval(0, 'boolean')
314
            ),
315
                'array'
316
            ),));
317
        $answer = '0101';
318
        $v = $this->send($m);
319
        if ($v) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $v of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
320
            $sz = $v->arraysize();
321
            $got = '';
322
            for ($i = 0; $i < $sz; $i++) {
323
                $b = $v->arraymem($i);
324
                if ($b->scalarval()) {
325
                    $got .= '1';
326
                } else {
327
                    $got .= '0';
328
                }
329
            }
330
            $this->assertEquals($answer, $got);
331
        }
332
    }
333
334
    public function testBase64()
335
    {
336
        $sendString = 'Mary had a little lamb,
337
Whose fleece was white as snow,
338
And everywhere that Mary went
339
the lamb was sure to go.
340
341
Mary had a little lamb
342
She tied it to a pylon
343
Ten thousand volts went down its back
344
And turned it into nylon';
345
        $m = new xmlrpcmsg('examples.decode64', array(
346
            new xmlrpcval($sendString, 'base64'),
347
        ));
348
        $v = $this->send($m);
349
        if ($v) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $v of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
350
            if (strlen($sendString) == strlen($v->scalarval())) {
351
                $this->assertEquals($sendString, $v->scalarval());
352
            } else {
353
                $this->assertEquals(str_replace(array("\r\n", "\r"), array("\n", "\n"), $sendString), $v->scalarval());
354
            }
355
        }
356
    }
357
358
    public function testCountEntities()
359
    {
360
        $sendString = "h'fd>onc>>l>>rw&bpu>q>e<v&gxs<ytjzkami<";
361
        $m = new xmlrpcmsg('validator1.countTheEntities', array(
362
            new xmlrpcval($sendString, 'string'),
363
        ));
364
        $v = $this->send($m);
365
        if ($v) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $v of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
366
            $got = '';
367
            $expected = '37210';
368
            $expect_array = array('ctLeftAngleBrackets', 'ctRightAngleBrackets', 'ctAmpersands', 'ctApostrophes', 'ctQuotes');
369
            foreach($expect_array as $val) {
370
                $b = $v->structmem($val);
371
                $got .= $b->me['int'];
372
            }
373
            $this->assertEquals($expected, $got);
374
        }
375
    }
376
377
    protected function _multicall_msg($method, $params)
378
    {
379
        $struct = array();
380
        $struct['methodName'] = new xmlrpcval($method, 'string');
381
        $struct['params'] = new xmlrpcval($params, 'array');
382
383
        return new xmlrpcval($struct, 'struct');
384
    }
385
386
    public function testServerMulticall()
387
    {
388
        // We manually construct a system.multicall() call to ensure
389
        // that the server supports it.
390
391
        // NB: This test will NOT pass if server does not support system.multicall.
392
393
        // Based on http://xmlrpc-c.sourceforge.net/hacks/test_multicall.py
394
        $good1 = $this->_multicall_msg(
395
            'system.methodHelp',
396
            array(php_xmlrpc_encode('system.listMethods')));
397
        $bad = $this->_multicall_msg(
398
            'test.nosuch',
399
            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
400
        $recursive = $this->_multicall_msg(
401
            'system.multicall',
402
            array(new xmlrpcval(array(), 'array')));
403
        $good2 = $this->_multicall_msg(
404
            'system.methodSignature',
405
            array(php_xmlrpc_encode('system.listMethods')));
406
        $arg = new xmlrpcval(
407
            array($good1, $bad, $recursive, $good2),
408
            'array'
409
        );
410
411
        $m = new xmlrpcmsg('system.multicall', array($arg));
412
        $v = $this->send($m);
413
        if ($v) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $v of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
414
            //$this->assertEquals(0, $r->faultCode(), "fault from system.multicall");
415
            $this->assertEquals(4, $v->arraysize(), "bad number of return values");
416
417
            $r1 = $v->arraymem(0);
418
            $this->assertTrue(
419
                $r1->kindOf() == 'array' && $r1->arraysize() == 1,
420
                "did not get array of size 1 from good1"
421
            );
422
423
            $r2 = $v->arraymem(1);
424
            $this->assertEquals('struct', $r2->kindOf(), "no fault from bad");
425
426
            $r3 = $v->arraymem(2);
427
            $this->assertEquals('struct', $r3->kindOf(), "recursive system.multicall did not fail");
428
429
            $r4 = $v->arraymem(3);
430
            $this->assertTrue(
431
                $r4->kindOf() == 'array' && $r4->arraysize() == 1,
432
                "did not get array of size 1 from good2"
433
            );
434
        }
435
    }
436
437
    public function testClientMulticall1()
438
    {
439
        // NB: This test will NOT pass if server does not support system.multicall.
440
441
        $noMultiCall = $this->client->no_multicall;
442
        $this->client->no_multicall = false;
443
444
        $good1 = new xmlrpcmsg('system.methodHelp',
445
            array(php_xmlrpc_encode('system.listMethods')));
446
        $bad = new xmlrpcmsg('test.nosuch',
447
            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
448
        $recursive = new xmlrpcmsg('system.multicall',
449
            array(new xmlrpcval(array(), 'array')));
450
        $good2 = new xmlrpcmsg('system.methodSignature',
451
            array(php_xmlrpc_encode('system.listMethods'))
452
        );
453
454
        $r = $this->send(array($good1, $bad, $recursive, $good2));
455
        if ($r) {
456
            $this->assertEquals(4, count($r), "wrong number of return values");
0 ignored issues
show
Bug introduced by
It seems like $r can also be of type integer; however, parameter $value of count() does only seem to accept Countable|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

456
            $this->assertEquals(4, count(/** @scrutinizer ignore-type */ $r), "wrong number of return values");
Loading history...
457
        }
458
459
        $this->assertEquals(0, $r[0]->faultCode(), "fault from good1");
460
        if (!$r[0]->faultCode()) {
461
            $val = $r[0]->value();
462
            $this->assertTrue(
463
                $val->kindOf() == 'scalar' && $val->scalartyp() == 'string',
464
                "good1 did not return string"
465
            );
466
        }
467
        $this->assertNotEquals(0, $r[1]->faultCode(), "no fault from bad");
468
        $this->assertNotEquals(0, $r[2]->faultCode(), "no fault from recursive system.multicall");
469
        $this->assertEquals(0, $r[3]->faultCode(), "fault from good2");
470
        if (!$r[3]->faultCode()) {
471
            $val = $r[3]->value();
472
            $this->assertEquals('array', $val->kindOf(), "good2 did not return array");
473
        }
474
        // This is the only assert in this test which should fail
475
        // if the test server does not support system.multicall.
476
        $this->assertEquals(false, $this->client->no_multicall, "server does not support system.multicall");
477
478
        $this->client->no_multicall = $noMultiCall;
479
    }
480
481
    public function testClientMulticall2()
482
    {
483
        // NB: This test will NOT pass if server does not support system.multicall.
484
485
        $noMultiCall = $this->client->no_multicall;
486
        $this->client->no_multicall = true;
487
488
        $good1 = new xmlrpcmsg('system.methodHelp',
489
            array(php_xmlrpc_encode('system.listMethods')));
490
        $bad = new xmlrpcmsg('test.nosuch',
491
            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
492
        $recursive = new xmlrpcmsg('system.multicall',
493
            array(new xmlrpcval(array(), 'array')));
494
        $good2 = new xmlrpcmsg('system.methodSignature',
495
            array(php_xmlrpc_encode('system.listMethods'))
496
        );
497
498
        $r = $this->send(array($good1, $bad, $recursive, $good2));
499
        if ($r) {
500
            $this->assertEquals(4, count($r), "wrong number of return values");
0 ignored issues
show
Bug introduced by
It seems like $r can also be of type integer; however, parameter $value of count() does only seem to accept Countable|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

500
            $this->assertEquals(4, count(/** @scrutinizer ignore-type */ $r), "wrong number of return values");
Loading history...
501
        }
502
503
        $this->assertEquals(0, $r[0]->faultCode(), "fault from good1");
504
        if (!$r[0]->faultCode()) {
505
            $val = $r[0]->value();
506
            $this->assertTrue(
507
                $val->kindOf() == 'scalar' && $val->scalartyp() == 'string',
508
                "good1 did not return string");
509
        }
510
        $this->assertNotEquals(0, $r[1]->faultCode(), "no fault from bad");
511
        $this->assertEquals(0, $r[2]->faultCode(), "fault from (non recursive) system.multicall");
512
        $this->assertEquals(0, $r[3]->faultCode(), "fault from good2");
513
        if (!$r[3]->faultCode()) {
514
            $val = $r[3]->value();
515
            $this->assertEquals('array', $val->kindOf(), "good2 did not return array");
516
        }
517
518
        $this->client->no_multicall = $noMultiCall;
519
    }
520
521
    public function testClientMulticall3()
522
    {
523
        // NB: This test will NOT pass if server does not support system.multicall.
524
525
        $noMultiCall = $this->client->no_multicall;
526
        $returnType = $this->client->return_type;
527
528
        $this->client->return_type = 'phpvals';
529
        $this->client->no_multicall = false;
530
531
        $good1 = new xmlrpcmsg('system.methodHelp',
532
            array(php_xmlrpc_encode('system.listMethods')));
533
        $bad = new xmlrpcmsg('test.nosuch',
534
            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
535
        $recursive = new xmlrpcmsg('system.multicall',
536
            array(new xmlrpcval(array(), 'array')));
537
        $good2 = new xmlrpcmsg('system.methodSignature',
538
            array(php_xmlrpc_encode('system.listMethods'))
539
        );
540
541
        $r = $this->send(array($good1, $bad, $recursive, $good2));
542
        if ($r) {
543
            $this->assertEquals(4, count($r), "wrong number of return values");
0 ignored issues
show
Bug introduced by
It seems like $r can also be of type integer; however, parameter $value of count() does only seem to accept Countable|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

543
            $this->assertEquals(4, count(/** @scrutinizer ignore-type */ $r), "wrong number of return values");
Loading history...
544
        }
545
        $this->assertEquals(0, $r[0]->faultCode(), "fault from good1");
546
        if (!$r[0]->faultCode()) {
547
            $val = $r[0]->value();
548
            $this->assertIsString($val, "good1 did not return string");
549
        }
550
        $this->assertNotEquals(0, $r[1]->faultCode(), "no fault from bad");
551
        $this->assertNotEquals(0, $r[2]->faultCode(), "no fault from recursive system.multicall");
552
        $this->assertEquals(0, $r[3]->faultCode(), "fault from good2");
553
        if (!$r[3]->faultCode()) {
554
            $val = $r[3]->value();
555
            $this->assertIsArray($val, "good2 did not return array");
556
        }
557
558
        $this->client->return_type = $returnType;
559
        $this->client->no_multicall = $noMultiCall;
560
    }
561
562
    public function testClientMulticall4()
563
    {
564
        // NB: This test will NOT pass if server does not support system.multicall.
565
566
        $noMultiCall = $this->client->no_multicall;
567
        $returnType = $this->client->return_type;
568
569
        $this->client->return_type = 'xml';
570
        $this->client->no_multicall = false;
571
572
        $good1 = new xmlrpcmsg('system.methodHelp',
573
            array(php_xmlrpc_encode('system.listMethods')));
574
        $good2 = new xmlrpcmsg('system.methodSignature',
575
            array(php_xmlrpc_encode('system.listMethods'))
576
        );
577
578
        $r = $this->send(array($good1, $good2));
579
        if ($r) {
580
            $this->assertEquals(2, count($r), "wrong number of return values");
0 ignored issues
show
Bug introduced by
It seems like $r can also be of type integer; however, parameter $value of count() does only seem to accept Countable|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

580
            $this->assertEquals(2, count(/** @scrutinizer ignore-type */ $r), "wrong number of return values");
Loading history...
581
        }
582
        $this->assertEquals(0, $r[0]->faultCode(), "fault from good1");
583
        $this->assertEquals(0, $r[1]->faultCode(), "fault from good2");
584
585
        $hr = $r[0]->httpResponse();
586
        $this->assertEquals(200, $hr['status_code'], "http response of multicall has no status code");
587
        $this->assertEquals($r[0]->httpResponse(), $r[1]->httpResponse(), "http response of multicall items differs");
588
589
        $this->client->return_type = $returnType;
590
        $this->client->no_multicall = $noMultiCall;
591
    }
592
593
    public function testCatchWarnings()
594
    {
595
        $m = new xmlrpcmsg('tests.generatePHPWarning', array(
596
            new xmlrpcval('whatever', 'string'),
597
        ));
598
        $v = $this->send($m);
599
        if ($v) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $v of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
600
            $this->assertEquals(true, $v->scalarval());
601
        }
602
    }
603
604
    public function testCatchExceptions()
605
    {
606
        // this tests for the server to catch exceptions with error code 0
607
        $m = new xmlrpcmsg('tests.raiseException', array(
608
            new xmlrpcval(0, 'int'),
609
        ));
610
        $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...
611
612
        // these test for the different server exception catching modes
613
        $m = new xmlrpcmsg('tests.raiseException', array(
614
            new xmlrpcval(3, 'int'),
615
        ));
616
        $v = $this->send($m, $GLOBALS['xmlrpcerr']['server_error']);
617
        $this->addQueryParams(array('EXCEPTION_HANDLING' => 1));
618
        $v = $this->send($m, 3); // the error code of the expected exception
619
        $this->addQueryParams(array('EXCEPTION_HANDLING' => 2));
620
        // depending on whether display_errors is ON or OFF on the server, we will get back a different error here,
621
        // as php will generate an http status code of either 200 or 500...
622
        $v = $this->send($m, array($GLOBALS['xmlrpcerr']['invalid_return'], $GLOBALS['xmlrpcerr']['http_error']));
623
    }
624
625
    public function testCatchErrors()
626
    {
627
        if (version_compare(PHP_VERSION, '7.0.0', '<'))
628
        {
629
            $this->markTestSkipped('cannot test php Error on php < 7.0');
630
            return;
631
        }
632
633
        // these test for the different server error catching modes
634
        $m = new xmlrpcmsg('tests.raiseError');
635
        $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...
636
        $this->addQueryParams(array('EXCEPTION_HANDLING' => 1));
637
        $v = $this->send($m, 1); // the error code of the expected exception
638
        $this->addQueryParams(array('EXCEPTION_HANDLING' => 2));
639
        // depending on whether display_errors is ON or OFF on the server, we will get back a different error here,
640
        // as php will generate an http status code of either 200 or 500...
641
        $v = $this->send($m, array($GLOBALS['xmlrpcerr']['invalid_return'], $GLOBALS['xmlrpcerr']['http_error']));
642
    }
643
644
    public function testZeroParams()
645
    {
646
        $m = new xmlrpcmsg('system.listMethods');
647
        $v = $this->send($m);
0 ignored issues
show
Unused Code introduced by
The assignment to $v is dead and can be removed.
Loading history...
648
    }
649
650
    public function testNullParams()
651
    {
652
        $m = new xmlrpcmsg('tests.getStateName.12', array(
653
            new xmlrpcval('whatever', 'null'),
654
            new xmlrpcval(23, 'int'),
655
        ));
656
        $v = $this->send($m);
657
        if ($v) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $v of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
658
            $this->assertEquals('Michigan', $v->scalarval());
659
        }
660
        $m = new xmlrpcmsg('tests.getStateName.12', array(
661
            new xmlrpcval(23, 'int'),
662
            new xmlrpcval('whatever', 'null'),
663
        ));
664
        $v = $this->send($m);
665
        if ($v) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $v of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
666
            $this->assertEquals('Michigan', $v->scalarval());
667
        }
668
        $m = new xmlrpcmsg('tests.getStateName.12', array(
669
            new xmlrpcval(23, 'int')
670
        ));
671
        $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...
672
    }
673
674
    public function testCodeInjectionServerSide()
675
    {
676
        $m = new xmlrpcmsg('system.MethodHelp');
677
        $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>";
678
        $v = $this->send($m);
679
        if ($v) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $v of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
680
            $this->assertEquals(0, $v->structsize());
681
        }
682
    }
683
684
    public function testServerWrappedFunction()
685
    {
686
        $m = new xmlrpcmsg('tests.getStateName.2', array(
687
            new xmlrpcval(23, 'int'),
688
        ));
689
        $v = $this->send($m);
690
        $this->assertEquals('Michigan', $v->scalarval());
691
692
        // this generates an exception in the function which was wrapped, which is by default wrapped in a known error response
693
        $m = new xmlrpcmsg('tests.getStateName.2', array(
694
            new xmlrpcval(0, 'int'),
695
        ));
696
        $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...
697
698
        // check if the generated function dispatch map is fine, by checking if the server registered it
699
        $m = new xmlrpcmsg('system.methodSignature', array(
700
            new xmlrpcval('tests.getStateName.2'),
701
        ));
702
        $v = $this->send($m);
703
        $encoder = new \PhpXmlRpc\Encoder();
704
        $this->assertEquals(array(array('string', 'int')), $encoder->decode($v));
0 ignored issues
show
Bug introduced by
It seems like $v can also be of type integer; however, parameter $xmlrpcVal of PhpXmlRpc\Encoder::decode() does only seem to accept PhpXmlRpc\Request|PhpXmlRpc\Value, 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

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

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
Bug Best Practice introduced by
The expression $v2 of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
995
            $this->assertEquals($v1, $v2);
996
        }
997
    }
998
999
    public function testNegativeDebug()
1000
    {
1001
        $m = new xmlrpcmsg('examples.stringecho', array(
1002
            new xmlrpcval('hello world', 'string'),
1003
        ));
1004
        $v1 = $this->send($m, 0, true);
1005
        $h = $v1->httpResponse();
1006
        $this->assertEquals('200', $h['status_code']);
1007
        $this->assertNotEmpty($h['headers']);
1008
1009
        $d = $this->client->debug;
1010
        $this->client->setDebug(-1);
1011
        $v2 = $this->send($m, 0, true);
1012
        $this->client->setDebug($d);
1013
        $h = $v2->httpResponse();
1014
        $this->assertEmpty($h['headers']);
1015
        $this->assertEmpty($h['raw_data']);
1016
    }
1017
}
1018