Passed
Push — master ( 2cae29...b6cd05 )
by Gaetano
12:23
created

ServerTest::testNegativeDebug()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 13
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 17
rs 9.8333
1
<?php
2
3
include_once __DIR__ . '/../lib/xmlrpc.inc';
4
include_once __DIR__ . '/../lib/xmlrpc_wrappers.inc';
5
6
include_once __DIR__ . '/parse_args.php';
7
8
include_once __DIR__ . '/PolyfillTestCase.php';
9
10
use PHPUnit\Extensions\SeleniumCommon\RemoteCoverage;
11
use PHPUnit\Framework\TestResult;
12
use PHPUnit\Runner\BaseTestRunner;
13
14
/**
15
 * Tests which involve interaction with the server - carried out via the client.
16
 * They are run against the server found in demo/server.php.
17
 * Includes testing of (some of) the Wrapper class
18
 */
19
class ServerTest extends PhpXmlRpc_PolyfillTestCase
20
{
21
    /** @var xmlrpc_client $client */
22
    protected $client = null;
23
    protected $method = 'http';
24
    protected $timeout = 10;
25
    protected $request_compression = null;
26
    protected $accepted_compression = '';
27
    protected $args = array();
28
29
    protected static $failed_tests = array();
30
31
    protected $testId;
32
    /** @var boolean $collectCodeCoverageInformation */
33
    protected $collectCodeCoverageInformation;
34
    protected $coverageScriptUrl;
35
36
    /**
37
     * @todo instead of overriding fail via _fail, implement Yoast\PHPUnitPolyfills\TestListeners\TestListenerDefaultImplementation
38
     */
39
    public static function _fail($message = '')
40
    {
41
        // save in a static var that this particular test has failed
42
        // (but only if not called from subclass objects / multitests)
43
        if (function_exists('debug_backtrace') && strtolower(get_called_class()) == 'localhosttests') {
44
            $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
45
            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...
46
                if (strpos($trace[$i]['function'], 'test') === 0) {
47
                    self::$failed_tests[$trace[$i]['function']] = true;
48
                    break;
49
                }
50
            }
51
        }
52
53
        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

53
        parent::/** @scrutinizer ignore-call */ 
54
                _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...
54
    }
55
56
    /**
57
     * Reimplemented to allow us to collect code coverage info from the target server.
58
     * Code taken from PHPUnit_Extensions_Selenium2TestCase
59
     *
60
     * @param TestResult $result
61
     * @return TestResult
62
     * @throws Exception
63
     *
64
     * @todo instead of overriding run via _run, try to achieve this by implementing Yoast\PHPUnitPolyfills\TestListeners\TestListenerDefaultImplementation
65
     */
66
    public function _run($result = NULL)
67
    {
68
        $this->testId = get_class($this) . '__' . $this->getName();
69
70
        if ($result === NULL) {
71
            $result = $this->createResult();
72
        }
73
74
        $this->collectCodeCoverageInformation = $result->getCollectCodeCoverageInformation();
75
76
        parent::_run($result);
77
78
        if ($this->collectCodeCoverageInformation) {
79
            $coverage = new RemoteCoverage(
80
                $this->coverageScriptUrl,
81
                $this->testId
82
            );
83
            $result->getCodeCoverage()->append(
84
                $coverage->get(), $this
85
            );
86
        }
87
88
        // do not call this before to give the time to the Listeners to run
89
        //$this->getStrategy()->endOfTest($this->session);
90
91
        return $result;
92
    }
93
94
    public function set_up()
95
    {
96
        $this->args = argParser::getArgs();
97
98
        $server = explode(':', $this->args['HTTPSERVER']);
99
        if (count($server) > 1) {
100
            $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

100
            $this->client = new xmlrpc_client($this->args['HTTPURI'], $server[0], /** @scrutinizer ignore-type */ $server[1]);
Loading history...
101
        } else {
102
            $this->client = new xmlrpc_client($this->args['HTTPURI'], $this->args['HTTPSERVER']);
103
        }
104
105
        $this->client->setDebug($this->args['DEBUG']);
106
        $this->client->request_compression = $this->request_compression;
107
        $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...
108
109
        $this->coverageScriptUrl = 'http://' . $this->args['HTTPSERVER'] . preg_replace('|/tests/index\.php(\?.*)?|', '/tests/phpunit_coverage.php', $this->args['HTTPURI']);
110
111
        // in debug mode, the client will be very verbose. Avoid showing its output unless there are errors
112
        if ($this->args['DEBUG'] >= 1)
113
            ob_start();
114
    }
115
116
    protected function tear_down()
117
    {
118
        if ($this->args['DEBUG'] < 1)
119
            return;
120
        $out = ob_get_clean();
121
        $status = $this->getStatus();
122
        if ($status == BaseTestRunner::STATUS_ERROR
123
            || $status == BaseTestRunner::STATUS_FAILURE) {
124
            echo $out;
125
        }
126
    }
127
128
    /**
129
     * @param PhpXmlRpc\Request|array $msg
130
     * @param int|array $errorCode expected error codes
131
     * @param bool $returnResponse
132
     * @return mixed|\PhpXmlRpc\Response|\PhpXmlRpc\Response[]|\PhpXmlRpc\Value|string|null
133
     */
134
    protected function send($msg, $errorCode = 0, $returnResponse = false)
135
    {
136
        if ($this->collectCodeCoverageInformation) {
137
            $this->client->setCookie('PHPUNIT_SELENIUM_TEST_ID', $this->testId);
138
        }
139
140
        $r = $this->client->send($msg, $this->timeout, $this->method);
141
        // for multicall, return directly array of responses
142
        if (is_array($r)) {
143
            return $r;
144
        }
145
        $this->validateResponse($r);
146
        if (is_array($errorCode)) {
147
            $this->assertContains($r->faultCode(), $errorCode, 'Error ' . $r->faultCode() . ' connecting to server: ' . $r->faultString());
148
        } else {
149
            $this->assertEquals($errorCode, $r->faultCode(), 'Error ' . $r->faultCode() . ' connecting to server: ' . $r->faultString());
150
        }
151
        if (!$r->faultCode()) {
152
            if ($returnResponse) {
153
                return $r;
154
            } else {
155
                return $r->value();
156
            }
157
        } else {
158
            return null;
159
        }
160
    }
161
162
    protected function validateResponse($r)
163
    {
164
        // to be implemented in subclasses
165
    }
166
167
    /**
168
     * Adds (and replaces) query params to the url currently used by the client
169
     * @param array $data
170
     */
171
    protected function addQueryParams($data)
172
    {
173
        $query = parse_url($this->client->path, PHP_URL_QUERY);
174
        parse_str($query, $vars);
175
        $query = http_build_query(array_merge($vars, $data));
176
        $this->client->path = parse_url($this->client->path, PHP_URL_PATH) . '?' . $query;
177
    }
178
179
    public function testString()
180
    {
181
        $sendString = "here are 3 \"entities\": < > & " .
182
            "and here's a dollar sign: \$pretendvarname and a backslash too: " . chr(92) .
183
            " - isn't that great? \\\"hackery\\\" at it's best " .
184
            " also don't want to miss out on \$item[0]. " .
185
            "The real weird stuff follows: CRLF here" . chr(13) . chr(10) .
186
            "a simple CR here" . chr(13) .
187
            "a simple LF here" . chr(10) .
188
            "and then LFCR" . chr(10) . chr(13) .
189
            "last but not least weird names: G" . chr(252) . "nter, El" . chr(232) . "ne, and an xml comment closing tag: -->";
190
        $m = new xmlrpcmsg('examples.stringecho', array(
191
            new xmlrpcval($sendString, 'string'),
192
        ));
193
        $v = $this->send($m);
194
        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...
195
            // when sending/receiving non-US-ASCII encoded strings, XML says cr-lf can be normalized.
196
            // so we relax our tests...
197
            $l1 = strlen($sendString);
198
            $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

198
            $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...
199
            if ($l1 == $l2) {
200
                $this->assertEquals($sendString, $v->scalarval());
201
            } else {
202
                $this->assertEquals(str_replace(array("\r\n", "\r"), array("\n", "\n"), $sendString), $v->scalarval());
203
            }
204
        }
205
    }
206
207
    public function testLatin1String()
208
    {
209
        $sendString =
210
            "last but not least weird names: G" . chr(252) . "nter, El" . chr(232) . "ne";
211
        $x = '<?xml version="1.0" encoding="ISO-8859-1"?><methodCall><methodName>examples.stringecho</methodName><params><param><value>'.
212
            $sendString.
213
            '</value></param></params></methodCall>';
214
        $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

214
        $v = $this->send(/** @scrutinizer ignore-type */ $x);
Loading history...
215
        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...
216
            $this->assertEquals($sendString, $v->scalarval());
217
        }
218
    }
219
220
    public function testExoticCharsetsRequests()
221
    {
222
        // note that we should disable this call also when mbstring is missing server-side
223
        if (!function_exists('mb_convert_encoding')) {
224
            $this->markTestSkipped('Miss mbstring extension to test exotic charsets');
225
            return;
226
        }
227
        $sendString = 'κόσμε'; // Greek word 'kosme'
228
        $str = '<?xml version="1.0" encoding="_ENC_"?>
229
<methodCall>
230
    <methodName>examples.stringecho</methodName>
231
    <params>
232
        <param>
233
        <value><string>'.$sendString.'</string></value>
234
        </param>
235
    </params>
236
</methodCall>';
237
238
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'UTF-8';
239
        // This test is known to fail with old mbstring versions, at least the ones we get with php 5.4, 5.5 as present
240
        // in the CI test vms
241
        if (version_compare(PHP_VERSION, '5.6.0', '>=')) {
242
            // we have to set the encoding declaration either in the http header or xml prolog, as mb_detect_encoding
243
            // (used on the server side) will fail recognizing these 2 charsets
244
            $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

244
            $v = $this->send(/** @scrutinizer ignore-type */ mb_convert_encoding(str_replace('_ENC_', 'UCS-4', $str), 'UCS-4', 'UTF-8'));
Loading history...
245
            $this->assertEquals($sendString, $v->scalarval());
246
        }
247
        $v = $this->send(mb_convert_encoding(str_replace('_ENC_', 'UTF-16', $str), 'UTF-16', 'UTF-8'));
248
        $this->assertEquals($sendString, $v->scalarval());
249
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
250
    }
251
252
    public function testExoticCharsetsRequests2()
253
    {
254
        // note that we should disable this call also when mbstring is missing server-side
255
        if (!function_exists('mb_convert_encoding')) {
256
            $this->markTestSkipped('Miss mbstring extension to test exotic charsets');
257
            return;
258
        }
259
        $sendString = '安室奈美恵'; // Japanese name "Namie Amuro"
260
        $str = '<?xml version="1.0"?>
261
<methodCall>
262
    <methodName>examples.stringecho</methodName>
263
    <params>
264
        <param>
265
        <value><string>'.$sendString.'</string></value>
266
        </param>
267
    </params>
268
</methodCall>';
269
270
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'UTF-8';
271
        // no encoding declaration either in the http header or xml prolog, let mb_detect_encoding
272
        // (used on the server side) sort it out
273
        $this->addQueryParams(array('DETECT_ENCODINGS' => array('EUC-JP', 'UTF-8')));
274
        $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

274
        $v = $this->send(/** @scrutinizer ignore-type */ mb_convert_encoding($str, 'EUC-JP', 'UTF-8'));
Loading history...
275
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
276
        $this->assertEquals($sendString, $v->scalarval());
277
    }
278
279
    public function testExoticCharsetsRequests3()
280
    {
281
        // note that we should disable this call also when mbstring is missing server-side
282
        if (!function_exists('mb_convert_encoding')) {
283
            $this->markTestSkipped('Miss mbstring extension to test exotic charsets');
284
            return;
285
        }
286
        // the warning suppression is due to utf8_decode being deprecated in php 8.2
287
        $sendString = @utf8_decode('élève');
288
        $str = '<?xml version="1.0"?>
289
<methodCall>
290
    <methodName>examples.stringecho</methodName>
291
    <params>
292
        <param>
293
        <value><string>'.$sendString.'</string></value>
294
        </param>
295
    </params>
296
</methodCall>';
297
298
        // no encoding declaration either in the http header or xml prolog, let mb_detect_encoding
299
        // (used on the server side) sort it out
300
        $this->addQueryParams(array('DETECT_ENCODINGS' => array('ISO-8859-1', 'UTF-8')));
301
        $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

301
        $v = $this->send(/** @scrutinizer ignore-type */ $str);
Loading history...
302
        $this->assertEquals($sendString, $v->scalarval());
303
    }
304
305
    /*public function testLatin1Method()
306
    {
307
        $f = new xmlrpcmsg("tests.iso88591methodname." . chr(224) . chr(252) . chr(232), array(
308
            new xmlrpcval('hello')
309
        ));
310
        $v = $this->send($f);
311
        if ($v) {
312
            $this->assertEquals('hello', $v->scalarval());
313
        }
314
    }*/
315
316
    public function testUtf8Method()
317
    {
318
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'UTF-8';
319
        $m = new xmlrpcmsg("tests.utf8methodname." . 'κόσμε', array(
320
            new xmlrpcval('hello')
321
        ));
322
        $v = $this->send($m);
323
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
324
        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...
325
            $this->assertEquals('hello', $v->scalarval());
326
        }
327
    }
328
329
    public function testAddingDoubles()
330
    {
331
        // note that rounding errors mean we keep precision to sensible levels here ;-)
332
        $a = 12.13;
333
        $b = -23.98;
334
        $m = new xmlrpcmsg('examples.addtwodouble', array(
335
            new xmlrpcval($a, 'double'),
336
            new xmlrpcval($b, 'double'),
337
        ));
338
        $v = $this->send($m);
339
        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...
340
            $this->assertEquals($a + $b, $v->scalarval());
341
        }
342
    }
343
344
    public function testAdding()
345
    {
346
        $m = new xmlrpcmsg('examples.addtwo', array(
347
            new xmlrpcval(12, 'int'),
348
            new xmlrpcval(-23, 'int'),
349
        ));
350
        $v = $this->send($m);
351
        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...
352
            $this->assertEquals(12 - 23, $v->scalarval());
353
        }
354
    }
355
356
    public function testInvalidNumber()
357
    {
358
        $m = new xmlrpcmsg('examples.addtwo', array(
359
            new xmlrpcval('fred', 'int'),
360
            new xmlrpcval("\"; exec('ls')", 'int'),
361
        ));
362
        $v = $this->send($m);
363
        /// @todo a specific fault should be generated here by the server, which we can check
364
        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...
365
            $this->assertEquals(0, $v->scalarval());
366
        }
367
    }
368
369
    public function testUnknownMethod()
370
    {
371
        $m = new xmlrpcmsg('examples.a_very_unlikely.method', array());
372
        $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...
373
    }
374
375
    public function testBoolean()
376
    {
377
        $m = new xmlrpcmsg('examples.invertBooleans', array(
378
            new xmlrpcval(array(
379
                new xmlrpcval(true, 'boolean'),
380
                new xmlrpcval(false, 'boolean'),
381
                new xmlrpcval(1, 'boolean'),
382
                new xmlrpcval(0, 'boolean')
383
            ),
384
                'array'
385
            ),));
386
        $answer = '0101';
387
        $v = $this->send($m);
388
        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...
389
            $sz = $v->arraysize();
390
            $got = '';
391
            for ($i = 0; $i < $sz; $i++) {
392
                $b = $v->arraymem($i);
393
                if ($b->scalarval()) {
394
                    $got .= '1';
395
                } else {
396
                    $got .= '0';
397
                }
398
            }
399
            $this->assertEquals($answer, $got);
400
        }
401
    }
402
403
    public function testBase64()
404
    {
405
        $sendString = 'Mary had a little lamb,
406
Whose fleece was white as snow,
407
And everywhere that Mary went
408
the lamb was sure to go.
409
410
Mary had a little lamb
411
She tied it to a pylon
412
Ten thousand volts went down its back
413
And turned it into nylon';
414
        $m = new xmlrpcmsg('examples.decode64', array(
415
            new xmlrpcval($sendString, 'base64'),
416
        ));
417
        $v = $this->send($m);
418
        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...
419
            if (strlen($sendString) == strlen($v->scalarval())) {
420
                $this->assertEquals($sendString, $v->scalarval());
421
            } else {
422
                $this->assertEquals(str_replace(array("\r\n", "\r"), array("\n", "\n"), $sendString), $v->scalarval());
423
            }
424
        }
425
    }
426
427
    public function testCountEntities()
428
    {
429
        $sendString = "h'fd>onc>>l>>rw&bpu>q>e<v&gxs<ytjzkami<";
430
        $m = new xmlrpcmsg('validator1.countTheEntities', array(
431
            new xmlrpcval($sendString, 'string'),
432
        ));
433
        $v = $this->send($m);
434
        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...
435
            $got = '';
436
            $expected = '37210';
437
            $expect_array = array('ctLeftAngleBrackets', 'ctRightAngleBrackets', 'ctAmpersands', 'ctApostrophes', 'ctQuotes');
438
            foreach($expect_array as $val) {
439
                $b = $v->structmem($val);
440
                $got .= $b->me['int'];
441
            }
442
            $this->assertEquals($expected, $got);
443
        }
444
    }
445
446
    protected function _multicall_msg($method, $params)
447
    {
448
        $struct = array();
449
        $struct['methodName'] = new xmlrpcval($method, 'string');
450
        $struct['params'] = new xmlrpcval($params, 'array');
451
452
        return new xmlrpcval($struct, 'struct');
453
    }
454
455
    public function testServerMulticall()
456
    {
457
        // We manually construct a system.multicall() call to ensure
458
        // that the server supports it.
459
460
        // NB: This test will NOT pass if server does not support system.multicall.
461
462
        // Based on http://xmlrpc-c.sourceforge.net/hacks/test_multicall.py
463
        $good1 = $this->_multicall_msg(
464
            'system.methodHelp',
465
            array(php_xmlrpc_encode('system.listMethods')));
466
        $bad = $this->_multicall_msg(
467
            'test.nosuch',
468
            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
469
        $recursive = $this->_multicall_msg(
470
            'system.multicall',
471
            array(new xmlrpcval(array(), 'array')));
472
        $good2 = $this->_multicall_msg(
473
            'system.methodSignature',
474
            array(php_xmlrpc_encode('system.listMethods')));
475
        $arg = new xmlrpcval(
476
            array($good1, $bad, $recursive, $good2),
477
            'array'
478
        );
479
480
        $m = new xmlrpcmsg('system.multicall', array($arg));
481
        $v = $this->send($m);
482
        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...
483
            //$this->assertEquals(0, $r->faultCode(), "fault from system.multicall");
484
            $this->assertEquals(4, $v->arraysize(), "bad number of return values");
485
486
            $r1 = $v->arraymem(0);
487
            $this->assertTrue(
488
                $r1->kindOf() == 'array' && $r1->arraysize() == 1,
489
                "did not get array of size 1 from good1"
490
            );
491
492
            $r2 = $v->arraymem(1);
493
            $this->assertEquals('struct', $r2->kindOf(), "no fault from bad");
494
495
            $r3 = $v->arraymem(2);
496
            $this->assertEquals('struct', $r3->kindOf(), "recursive system.multicall did not fail");
497
498
            $r4 = $v->arraymem(3);
499
            $this->assertTrue(
500
                $r4->kindOf() == 'array' && $r4->arraysize() == 1,
501
                "did not get array of size 1 from good2"
502
            );
503
        }
504
    }
505
506
    public function testClientMulticall1()
507
    {
508
        // NB: This test will NOT pass if server does not support system.multicall.
509
510
        $noMultiCall = $this->client->no_multicall;
511
        $this->client->no_multicall = false;
512
513
        $good1 = new xmlrpcmsg('system.methodHelp',
514
            array(php_xmlrpc_encode('system.listMethods')));
515
        $bad = new xmlrpcmsg('test.nosuch',
516
            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
517
        $recursive = new xmlrpcmsg('system.multicall',
518
            array(new xmlrpcval(array(), 'array')));
519
        $good2 = new xmlrpcmsg('system.methodSignature',
520
            array(php_xmlrpc_encode('system.listMethods'))
521
        );
522
523
        $r = $this->send(array($good1, $bad, $recursive, $good2));
524
        if ($r) {
525
            $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

525
            $this->assertEquals(4, count(/** @scrutinizer ignore-type */ $r), "wrong number of return values");
Loading history...
526
        }
527
528
        $this->assertEquals(0, $r[0]->faultCode(), "fault from good1");
529
        if (!$r[0]->faultCode()) {
530
            $val = $r[0]->value();
531
            $this->assertTrue(
532
                $val->kindOf() == 'scalar' && $val->scalartyp() == 'string',
533
                "good1 did not return string"
534
            );
535
        }
536
        $this->assertNotEquals(0, $r[1]->faultCode(), "no fault from bad");
537
        $this->assertNotEquals(0, $r[2]->faultCode(), "no fault from recursive system.multicall");
538
        $this->assertEquals(0, $r[3]->faultCode(), "fault from good2");
539
        if (!$r[3]->faultCode()) {
540
            $val = $r[3]->value();
541
            $this->assertEquals('array', $val->kindOf(), "good2 did not return array");
542
        }
543
        // This is the only assert in this test which should fail
544
        // if the test server does not support system.multicall.
545
        $this->assertEquals(false, $this->client->no_multicall, "server does not support system.multicall");
546
547
        $this->client->no_multicall = $noMultiCall;
548
    }
549
550
    public function testClientMulticall2()
551
    {
552
        // NB: This test will NOT pass if server does not support system.multicall.
553
554
        $noMultiCall = $this->client->no_multicall;
555
        $this->client->no_multicall = true;
556
557
        $good1 = new xmlrpcmsg('system.methodHelp',
558
            array(php_xmlrpc_encode('system.listMethods')));
559
        $bad = new xmlrpcmsg('test.nosuch',
560
            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
561
        $recursive = new xmlrpcmsg('system.multicall',
562
            array(new xmlrpcval(array(), 'array')));
563
        $good2 = new xmlrpcmsg('system.methodSignature',
564
            array(php_xmlrpc_encode('system.listMethods'))
565
        );
566
567
        $r = $this->send(array($good1, $bad, $recursive, $good2));
568
        if ($r) {
569
            $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

569
            $this->assertEquals(4, count(/** @scrutinizer ignore-type */ $r), "wrong number of return values");
Loading history...
570
        }
571
572
        $this->assertEquals(0, $r[0]->faultCode(), "fault from good1");
573
        if (!$r[0]->faultCode()) {
574
            $val = $r[0]->value();
575
            $this->assertTrue(
576
                $val->kindOf() == 'scalar' && $val->scalartyp() == 'string',
577
                "good1 did not return string");
578
        }
579
        $this->assertNotEquals(0, $r[1]->faultCode(), "no fault from bad");
580
        $this->assertEquals(0, $r[2]->faultCode(), "fault from (non recursive) system.multicall");
581
        $this->assertEquals(0, $r[3]->faultCode(), "fault from good2");
582
        if (!$r[3]->faultCode()) {
583
            $val = $r[3]->value();
584
            $this->assertEquals('array', $val->kindOf(), "good2 did not return array");
585
        }
586
587
        $this->client->no_multicall = $noMultiCall;
588
    }
589
590
    public function testClientMulticall3()
591
    {
592
        // NB: This test will NOT pass if server does not support system.multicall.
593
594
        $noMultiCall = $this->client->no_multicall;
595
        $returnType = $this->client->return_type;
596
597
        $this->client->return_type = 'phpvals';
598
        $this->client->no_multicall = false;
599
600
        $good1 = new xmlrpcmsg('system.methodHelp',
601
            array(php_xmlrpc_encode('system.listMethods')));
602
        $bad = new xmlrpcmsg('test.nosuch',
603
            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
604
        $recursive = new xmlrpcmsg('system.multicall',
605
            array(new xmlrpcval(array(), 'array')));
606
        $good2 = new xmlrpcmsg('system.methodSignature',
607
            array(php_xmlrpc_encode('system.listMethods'))
608
        );
609
610
        $r = $this->send(array($good1, $bad, $recursive, $good2));
611
        if ($r) {
612
            $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

612
            $this->assertEquals(4, count(/** @scrutinizer ignore-type */ $r), "wrong number of return values");
Loading history...
613
        }
614
        $this->assertEquals(0, $r[0]->faultCode(), "fault from good1");
615
        if (!$r[0]->faultCode()) {
616
            $val = $r[0]->value();
617
            $this->assertIsString($val, "good1 did not return string");
618
        }
619
        $this->assertNotEquals(0, $r[1]->faultCode(), "no fault from bad");
620
        $this->assertNotEquals(0, $r[2]->faultCode(), "no fault from recursive system.multicall");
621
        $this->assertEquals(0, $r[3]->faultCode(), "fault from good2");
622
        if (!$r[3]->faultCode()) {
623
            $val = $r[3]->value();
624
            $this->assertIsArray($val, "good2 did not return array");
625
        }
626
627
        $this->client->return_type = $returnType;
628
        $this->client->no_multicall = $noMultiCall;
629
    }
630
631
    public function testClientMulticall4()
632
    {
633
        // NB: This test will NOT pass if server does not support system.multicall.
634
635
        $noMultiCall = $this->client->no_multicall;
636
        $returnType = $this->client->return_type;
637
638
        $this->client->return_type = 'xml';
639
        $this->client->no_multicall = false;
640
641
        $good1 = new xmlrpcmsg('system.methodHelp',
642
            array(php_xmlrpc_encode('system.listMethods')));
643
        $good2 = new xmlrpcmsg('system.methodSignature',
644
            array(php_xmlrpc_encode('system.listMethods'))
645
        );
646
647
        $r = $this->send(array($good1, $good2));
648
        if ($r) {
649
            $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

649
            $this->assertEquals(2, count(/** @scrutinizer ignore-type */ $r), "wrong number of return values");
Loading history...
650
        }
651
        $this->assertEquals(0, $r[0]->faultCode(), "fault from good1");
652
        $this->assertEquals(0, $r[1]->faultCode(), "fault from good2");
653
654
        $hr = $r[0]->httpResponse();
655
        $this->assertEquals(200, $hr['status_code'], "http response of multicall has no status code");
656
        $this->assertEquals($r[0]->httpResponse(), $r[1]->httpResponse(), "http response of multicall items differs");
657
658
        $this->client->return_type = $returnType;
659
        $this->client->no_multicall = $noMultiCall;
660
    }
661
662
    public function testCatchWarnings()
663
    {
664
        $m = new xmlrpcmsg('tests.generatePHPWarning', array(
665
            new xmlrpcval('whatever', 'string'),
666
        ));
667
        $v = $this->send($m);
668
        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...
669
            $this->assertEquals(true, $v->scalarval());
670
        }
671
    }
672
673
    public function testCatchExceptions()
674
    {
675
        // this tests for the server to catch exceptions with error code 0
676
        $m = new xmlrpcmsg('tests.raiseException', array(
677
            new xmlrpcval(0, 'int'),
678
        ));
679
        $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...
680
681
        // these test for the different server exception catching modes
682
        $m = new xmlrpcmsg('tests.raiseException', array(
683
            new xmlrpcval(3, 'int'),
684
        ));
685
        $v = $this->send($m, $GLOBALS['xmlrpcerr']['server_error']);
686
        $this->addQueryParams(array('EXCEPTION_HANDLING' => 1));
687
        $v = $this->send($m, 3); // the error code of the expected exception
688
        $this->addQueryParams(array('EXCEPTION_HANDLING' => 2));
689
        // depending on whether display_errors is ON or OFF on the server, we will get back a different error here,
690
        // as php will generate an http status code of either 200 or 500...
691
        $v = $this->send($m, array($GLOBALS['xmlrpcerr']['invalid_return'], $GLOBALS['xmlrpcerr']['http_error']));
692
    }
693
694
    public function testCatchErrors()
695
    {
696
        if (version_compare(PHP_VERSION, '7.0.0', '<'))
697
        {
698
            $this->markTestSkipped('cannot test php Error on php < 7.0');
699
            return;
700
        }
701
702
        // these test for the different server error catching modes
703
        $m = new xmlrpcmsg('tests.raiseError');
704
        $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...
705
        $this->addQueryParams(array('EXCEPTION_HANDLING' => 1));
706
        $v = $this->send($m, 1); // the error code of the expected exception
707
        $this->addQueryParams(array('EXCEPTION_HANDLING' => 2));
708
        // depending on whether display_errors is ON or OFF on the server, we will get back a different error here,
709
        // as php will generate an http status code of either 200 or 500...
710
        $v = $this->send($m, array($GLOBALS['xmlrpcerr']['invalid_return'], $GLOBALS['xmlrpcerr']['http_error']));
711
    }
712
713
    public function testZeroParams()
714
    {
715
        $m = new xmlrpcmsg('system.listMethods');
716
        $v = $this->send($m);
0 ignored issues
show
Unused Code introduced by
The assignment to $v is dead and can be removed.
Loading history...
717
    }
718
719
    public function testNullParams()
720
    {
721
        $m = new xmlrpcmsg('tests.getStateName.12', array(
722
            new xmlrpcval('whatever', 'null'),
723
            new xmlrpcval(23, 'int'),
724
        ));
725
        $v = $this->send($m);
726
        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...
727
            $this->assertEquals('Michigan', $v->scalarval());
728
        }
729
        $m = new xmlrpcmsg('tests.getStateName.12', array(
730
            new xmlrpcval(23, 'int'),
731
            new xmlrpcval('whatever', 'null'),
732
        ));
733
        $v = $this->send($m);
734
        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...
735
            $this->assertEquals('Michigan', $v->scalarval());
736
        }
737
        $m = new xmlrpcmsg('tests.getStateName.12', array(
738
            new xmlrpcval(23, 'int')
739
        ));
740
        $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...
741
    }
742
743
    public function testCodeInjectionServerSide()
744
    {
745
        $m = new xmlrpcmsg('system.MethodHelp');
746
        $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>";
747
        $v = $this->send($m);
748
        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...
749
            $this->assertEquals(0, $v->structsize());
750
        }
751
    }
752
753
    public function testServerWrappedFunction()
754
    {
755
        $m = new xmlrpcmsg('tests.getStateName.2', array(
756
            new xmlrpcval(23, 'int'),
757
        ));
758
        $v = $this->send($m);
759
        $this->assertEquals('Michigan', $v->scalarval());
760
761
        // this generates an exception in the function which was wrapped, which is by default wrapped in a known error response
762
        $m = new xmlrpcmsg('tests.getStateName.2', array(
763
            new xmlrpcval(0, 'int'),
764
        ));
765
        $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...
766
767
        // check if the generated function dispatch map is fine, by checking if the server registered it
768
        $m = new xmlrpcmsg('system.methodSignature', array(
769
            new xmlrpcval('tests.getStateName.2'),
770
        ));
771
        $v = $this->send($m);
772
        $encoder = new \PhpXmlRpc\Encoder();
773
        $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

773
        $this->assertEquals(array(array('string', 'int')), $encoder->decode(/** @scrutinizer ignore-type */ $v));
Loading history...
774
    }
775
776
    public function testServerWrappedFunctionAsSource()
777
    {
778
        $m = new xmlrpcmsg('tests.getStateName.6', array(
779
            new xmlrpcval(23, 'int'),
780
        ));
781
        $v = $this->send($m);
782
        $this->assertEquals('Michigan', $v->scalarval());
783
784
        // this generates an exception in the function which was wrapped, which is by default wrapped in a known error response
785
        $m = new xmlrpcmsg('tests.getStateName.6', array(
786
            new xmlrpcval(0, 'int'),
787
        ));
788
        $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...
789
    }
790
791
    public function testServerWrappedObjectMethods()
792
    {
793
        $m = new xmlrpcmsg('tests.getStateName.3', array(
794
            new xmlrpcval(23, 'int'),
795
        ));
796
        $v = $this->send($m);
797
        $this->assertEquals('Michigan', $v->scalarval());
798
799
        $m = new xmlrpcmsg('tests.getStateName.4', array(
800
            new xmlrpcval(23, 'int'),
801
        ));
802
        $v = $this->send($m);
803
        $this->assertEquals('Michigan', $v->scalarval());
804
805
        $m = new xmlrpcmsg('tests.getStateName.5', array(
806
            new xmlrpcval(23, 'int'),
807
        ));
808
        $v = $this->send($m);
809
        $this->assertEquals('Michigan', $v->scalarval());
810
811
        $m = new xmlrpcmsg('tests.getStateName.7', array(
812
            new xmlrpcval(23, 'int'),
813
        ));
814
        $v = $this->send($m);
815
        $this->assertEquals('Michigan', $v->scalarval());
816
817
        $m = new xmlrpcmsg('tests.getStateName.8', array(
818
            new xmlrpcval(23, 'int'),
819
        ));
820
        $v = $this->send($m);
821
        $this->assertEquals('Michigan', $v->scalarval());
822
823
        $m = new xmlrpcmsg('tests.getStateName.9', array(
824
            new xmlrpcval(23, 'int'),
825
        ));
826
        $v = $this->send($m);
827
        $this->assertEquals('Michigan', $v->scalarval());
828
    }
829
830
    public function testServerWrappedObjectMethodsAsSource()
831
    {
832
        $m = new xmlrpcmsg('tests.getStateName.7', array(
833
            new xmlrpcval(23, 'int'),
834
        ));
835
        $v = $this->send($m);
836
        $this->assertEquals('Michigan', $v->scalarval());
837
838
        $m = new xmlrpcmsg('tests.getStateName.8', array(
839
            new xmlrpcval(23, 'int'),
840
        ));
841
        $v = $this->send($m);
842
        $this->assertEquals('Michigan', $v->scalarval());
843
844
        $m = new xmlrpcmsg('tests.getStateName.9', array(
845
            new xmlrpcval(23, 'int'),
846
        ));
847
        $v = $this->send($m);
848
        $this->assertEquals('Michigan', $v->scalarval());
849
    }
850
851
    public function testServerClosure()
852
    {
853
        $m = new xmlrpcmsg('tests.getStateName.10', array(
854
            new xmlrpcval(23, 'int'),
855
        ));
856
        $v = $this->send($m);
857
        $this->assertEquals('Michigan', $v->scalarval());
858
    }
859
860
    public function testServerWrappedClosure()
861
    {
862
        $m = new xmlrpcmsg('tests.getStateName.11', array(
863
            new xmlrpcval(23, 'int'),
864
        ));
865
        $v = $this->send($m);
866
        $this->assertEquals('Michigan', $v->scalarval());
867
    }
868
869
    public function testServerWrappedClass()
870
    {
871
        $m = new xmlrpcmsg('tests.handlersContainer.findState', array(
872
            new xmlrpcval(23, 'int'),
873
        ));
874
        $v = $this->send($m);
875
        $this->assertEquals('Michigan', $v->scalarval());
876
    }
877
878
    public function testServerWrappedClassWithNamespace()
879
    {
880
        $m = new xmlrpcmsg('namespacetest.findState', array(
881
            new xmlrpcval(23, 'int'),
882
        ));
883
        $v = $this->send($m);
884
        $this->assertEquals('Michigan', $v->scalarval());
885
    }
886
887
    public function testWrapInexistentMethod()
888
    {
889
        // make a 'deep client copy' as the original one might have many properties set
890
        $func = wrap_xmlrpc_method($this->client, 'examples.getStateName.notexisting', array('simple_client_copy' => 0));
891
        $this->assertEquals(false, $func);
892
    }
893
894
    public function testWrapInexistentUrl()
895
    {
896
        $this->client->path = '/notexisting';
897
        // make a 'deep client copy' as the original one might have many properties set
898
        $func = wrap_xmlrpc_method($this->client, 'examples.getStateName', array('simple_client_copy' => 0));
899
        $this->assertEquals(false, $func);
900
    }
901
902
    public function testWrappedMethod()
903
    {
904
        // make a 'deep client copy' as the original one might have many properties set
905
        $func = wrap_xmlrpc_method($this->client, 'examples.getStateName', array('simple_client_copy' => 0));
906
        if ($func == false) {
907
            $this->fail('Registration of examples.getStateName failed');
908
        } else {
909
            $v = $func(23);
910
            // work around bug in current (or old?) version of phpunit when reporting the error
911
            /*if (is_object($v)) {
912
                $v = var_export($v, true);
913
            }*/
914
            $this->assertEquals('Michigan', $v);
915
        }
916
    }
917
918
    public function testWrappedMethodAsSource()
919
    {
920
        // make a 'deep client copy' as the original one might have many properties set
921
        $func = wrap_xmlrpc_method($this->client, 'examples.getStateName', array('simple_client_copy' => 0, 'return_source' => true));
922
        if ($func == false) {
923
            $this->fail('Registration of examples.getStateName failed');
924
        } else {
925
            eval($func['source']);
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
926
            $func = $func['function'];
927
            $v = $func(23);
928
            // work around bug in current (or old?) version of phpunit when reporting the error
929
            /*if (is_object($v)) {
930
                $v = var_export($v, true);
931
            }*/
932
            $this->assertEquals('Michigan', $v);
933
        }
934
    }
935
936
    public function testWrappedClass()
937
    {
938
        // make a 'deep client copy' as the original one might have many properties set
939
        // also for speed only wrap one method of the whole server
940
        $class = wrap_xmlrpc_server($this->client, array('simple_client_copy' => 0, 'method_filter' => '/examples\.getStateName/' ));
941
        if ($class == '') {
942
            $this->fail('Registration of remote server failed');
943
        } else {
944
            $obj = new $class();
945
            if (!is_callable(array($obj, 'examples_getStateName'))) {
946
                $this->fail('Registration of remote server failed to import method "examples_getStateName"');
947
            } else {
948
                $v = $obj->examples_getStateName(23);
949
                // work around bug in current (or old?) version of phpunit when reporting the error
950
                /*if (is_object($v)) {
951
                    $v = var_export($v, true);
952
                }*/
953
                $this->assertEquals('Michigan', $v);
954
            }
955
        }
956
    }
957
958
    public function testTransferOfObjectViaWrapping()
959
    {
960
        // make a 'deep client copy' as the original one might have many properties set
961
        $func = wrap_xmlrpc_method($this->client, 'tests.returnPhpObject', array('simple_client_copy' => 0,
962
            'decode_php_objs' => true));
963
        if ($func == false) {
964
            $this->fail('Registration of tests.returnPhpObject failed');
965
        } else {
966
            $v = $func();
967
            $obj = new stdClass();
968
            $obj->hello = 'world';
969
            $this->assertEquals($obj, $v);
970
        }
971
    }
972
973
    public function testGetCookies()
974
    {
975
        // let server set to us some cookies we tell it
976
        $cookies = array(
977
            //'c1' => array(),
978
            'c2' => array('value' => 'c2'),
979
            'c3' => array('value' => 'c3', 'expires' => time() + 60 * 60 * 24 * 30),
980
            'c4' => array('value' => 'c4', 'expires' => time() + 60 * 60 * 24 * 30, 'path' => '/'),
981
            'c5' => array('value' => 'c5', 'expires' => time() + 60 * 60 * 24 * 30, 'path' => '/', 'domain' => 'localhost'),
982
        );
983
        $cookiesval = php_xmlrpc_encode($cookies);
984
        $m = new xmlrpcmsg('tests.setcookies', array($cookiesval));
985
        $r = $this->send($m, 0, true);
986
        if ($r) {
987
            $v = $r->value();
988
            $this->assertEquals(1, $v->scalarval());
989
            // now check if we decoded the cookies as we had set them
990
            $rcookies = $r->cookies();
991
            // remove extra cookies which might have been set by proxies
992
            foreach ($rcookies as $c => $v) {
993
                if (!in_array($c, array('c2', 'c3', 'c4', 'c5'))) {
994
                    unset($rcookies[$c]);
995
                }
996
                // Seems like we get this when using php-fpm and php 5.5+ ...
997
                if (isset($rcookies[$c]['Max-Age'])) {
998
                    unset($rcookies[$c]['Max-Age']);
999
                }
1000
            }
1001
            foreach ($cookies as $c => $v) {
1002
                // format for date string in cookies: 'Mon, 31 Oct 2005 13:50:56 GMT'
1003
                // but PHP versions differ on that, some use 'Mon, 31-Oct-2005 13:50:56 GMT'...
1004
                if (isset($v['expires'])) {
1005
                    if (isset($rcookies[$c]['expires']) && strpos($rcookies[$c]['expires'], '-')) {
1006
                        $cookies[$c]['expires'] = gmdate('D, d\-M\-Y H:i:s \G\M\T', $cookies[$c]['expires']);
1007
                    } else {
1008
                        $cookies[$c]['expires'] = gmdate('D, d M Y H:i:s \G\M\T', $cookies[$c]['expires']);
1009
                    }
1010
                }
1011
            }
1012
1013
            $this->assertEquals($cookies, $rcookies);
1014
        }
1015
    }
1016
1017
    public function testSetCookies()
1018
    {
1019
        // let server set to us some cookies we tell it
1020
        $cookies = array(
1021
            'c0' => null,
1022
            'c1' => 1,
1023
            'c2' => '2 3',
1024
            'c3' => '!@#$%^&*()_+|}{":?><,./\';[]\\=-',
1025
        );
1026
        $m = new xmlrpcmsg('tests.getcookies', array());
1027
        foreach ($cookies as $cookie => $val) {
1028
            $this->client->setCookie($cookie, $val);
1029
            $cookies[$cookie] = (string)$cookies[$cookie];
1030
        }
1031
        $r = $this->client->send($m, $this->timeout, $this->method);
1032
        $this->assertEquals(0, $r->faultCode(), 'Error ' . $r->faultCode() . ' connecting to server: ' . $r->faultString());
1033
        if (!$r->faultCode()) {
1034
            $v = $r->value();
1035
            $v = php_xmlrpc_decode($v);
1036
1037
            // take care for the extra cookie used for coverage collection
1038
            if (isset($v['PHPUNIT_SELENIUM_TEST_ID'])) {
1039
                unset($v['PHPUNIT_SELENIUM_TEST_ID']);
1040
            }
1041
1042
            // on IIS and Apache getallheaders returns something slightly different...
1043
            $this->assertEquals($cookies, $v);
1044
        }
1045
    }
1046
1047
    public function testServerComments()
1048
    {
1049
        $m = new xmlrpcmsg('tests.handlersContainer.debugMessageGenerator', array(
1050
            new xmlrpcval('hello world', 'string'),
1051
        ));
1052
        $r = $this->send($m, 0, true);
1053
        $this->assertStringContainsString('hello world', $r->raw_data);
1054
    }
1055
1056
    public function testSendTwiceSameMsg()
1057
    {
1058
        $m = new xmlrpcmsg('examples.stringecho', array(
1059
            new xmlrpcval('hello world', 'string'),
1060
        ));
1061
        $v1 = $this->send($m);
1062
        $v2 = $this->send($m);
1063
        if ($v1 && $v2) {
0 ignored issues
show
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...
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...
1064
            $this->assertEquals($v1, $v2);
1065
        }
1066
    }
1067
1068
    public function testNegativeDebug()
1069
    {
1070
        $m = new xmlrpcmsg('examples.stringecho', array(
1071
            new xmlrpcval('hello world', 'string'),
1072
        ));
1073
        $v1 = $this->send($m, 0, true);
1074
        $h = $v1->httpResponse();
1075
        $this->assertEquals('200', $h['status_code']);
1076
        $this->assertNotEmpty($h['headers']);
1077
1078
        $d = $this->client->debug;
1079
        $this->client->setDebug(-1);
1080
        $v2 = $this->send($m, 0, true);
1081
        $this->client->setDebug($d);
1082
        $h = $v2->httpResponse();
1083
        $this->assertEmpty($h['headers']);
1084
        $this->assertEmpty($h['raw_data']);
1085
    }
1086
}
1087