Passed
Push — master ( c803c8...b166f8 )
by Gaetano
05:21
created

ServerTest::testBase64()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 20
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

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

300
        $v = $this->send(/** @scrutinizer ignore-type */ $str);
Loading history...
301
        $this->assertEquals($sendString, $v->scalarval());
302
    }
303
304
    /*public function testLatin1Method()
305
    {
306
        $f = new xmlrpcmsg("tests.iso88591methodname." . chr(224) . chr(252) . chr(232), array(
307
            new xmlrpcval('hello')
308
        ));
309
        $v = $this->send($f);
310
        if ($v) {
311
            $this->assertEquals('hello', $v->scalarval());
312
        }
313
    }*/
314
315
    public function testUtf8Method()
316
    {
317
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'UTF-8';
318
        $m = new xmlrpcmsg("tests.utf8methodname." . 'κόσμε', array(
319
            new xmlrpcval('hello')
320
        ));
321
        $v = $this->send($m);
322
        PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
323
        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...
324
            $this->assertEquals('hello', $v->scalarval());
325
        }
326
    }
327
328
    public function testAddingDoubles()
329
    {
330
        // note that rounding errors mean we
331
        // 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 testDateTime()
428
    {
429
        $time = time();
430
        $t1 = new xmlrpcval($time, 'dateTime.iso8601');
431
        $t2 = new xmlrpcval(iso8601_encode($time), 'dateTime.iso8601');
432
        $this->assertEquals($t1->serialize(), $t2->serialize());
433
        if (class_exists('DateTime')) {
434
            $datetime = new DateTime();
435
            // skip this test for php 5.2. It is a bit harder there to build a DateTime from unix timestamp with proper TZ info
436
            if (is_callable(array($datetime, 'setTimestamp'))) {
437
                $t3 = new xmlrpcval($datetime->setTimestamp($time), 'dateTime.iso8601');
438
                $this->assertEquals($t1->serialize(), $t3->serialize());
439
            }
440
        }
441
    }
442
443
    public function testCountEntities()
444
    {
445
        $sendString = "h'fd>onc>>l>>rw&bpu>q>e<v&gxs<ytjzkami<";
446
        $m = new xmlrpcmsg('validator1.countTheEntities', array(
447
            new xmlrpcval($sendString, 'string'),
448
        ));
449
        $v = $this->send($m);
450
        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...
451
            $got = '';
452
            $expected = '37210';
453
            $expect_array = array('ctLeftAngleBrackets', 'ctRightAngleBrackets', 'ctAmpersands', 'ctApostrophes', 'ctQuotes');
454
            foreach($expect_array as $val) {
455
                $b = $v->structmem($val);
456
                $got .= $b->me['int'];
457
            }
458
            $this->assertEquals($expected, $got);
459
        }
460
    }
461
462
    public function _multicall_msg($method, $params)
463
    {
464
        $struct['methodName'] = new xmlrpcval($method, 'string');
0 ignored issues
show
Comprehensibility Best Practice introduced by
$struct was never initialized. Although not strictly required by PHP, it is generally a good practice to add $struct = array(); before regardless.
Loading history...
465
        $struct['params'] = new xmlrpcval($params, 'array');
466
467
        return new xmlrpcval($struct, 'struct');
468
    }
469
470
    public function testServerMulticall()
471
    {
472
        // We manually construct a system.multicall() call to ensure
473
        // that the server supports it.
474
475
        // NB: This test will NOT pass if server does not support system.multicall.
476
477
        // Based on http://xmlrpc-c.sourceforge.net/hacks/test_multicall.py
478
        $good1 = $this->_multicall_msg(
479
            'system.methodHelp',
480
            array(php_xmlrpc_encode('system.listMethods')));
481
        $bad = $this->_multicall_msg(
482
            'test.nosuch',
483
            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
484
        $recursive = $this->_multicall_msg(
485
            'system.multicall',
486
            array(new xmlrpcval(array(), 'array')));
487
        $good2 = $this->_multicall_msg(
488
            'system.methodSignature',
489
            array(php_xmlrpc_encode('system.listMethods')));
490
        $arg = new xmlrpcval(
491
            array($good1, $bad, $recursive, $good2),
492
            'array'
493
        );
494
495
        $m = new xmlrpcmsg('system.multicall', array($arg));
496
        $v = $this->send($m);
497
        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...
498
            //$this->assertEquals(0, $r->faultCode(), "fault from system.multicall");
499
            $this->assertEquals(4, $v->arraysize(), "bad number of return values");
500
501
            $r1 = $v->arraymem(0);
502
            $this->assertTrue(
503
                $r1->kindOf() == 'array' && $r1->arraysize() == 1,
504
                "did not get array of size 1 from good1"
505
            );
506
507
            $r2 = $v->arraymem(1);
508
            $this->assertEquals('struct', $r2->kindOf(), "no fault from bad");
509
510
            $r3 = $v->arraymem(2);
511
            $this->assertEquals('struct', $r3->kindOf(), "recursive system.multicall did not fail");
512
513
            $r4 = $v->arraymem(3);
514
            $this->assertTrue(
515
                $r4->kindOf() == 'array' && $r4->arraysize() == 1,
516
                "did not get array of size 1 from good2"
517
            );
518
        }
519
    }
520
521
    public function testClientMulticall1()
522
    {
523
        // NB: This test will NOT pass if server does not support system.multicall.
524
525
        $noMultiCall = $this->client->no_multicall;
526
        $this->client->no_multicall = false;
527
528
        $good1 = new xmlrpcmsg('system.methodHelp',
529
            array(php_xmlrpc_encode('system.listMethods')));
530
        $bad = new xmlrpcmsg('test.nosuch',
531
            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
532
        $recursive = new xmlrpcmsg('system.multicall',
533
            array(new xmlrpcval(array(), 'array')));
534
        $good2 = new xmlrpcmsg('system.methodSignature',
535
            array(php_xmlrpc_encode('system.listMethods'))
536
        );
537
538
        $r = $this->send(array($good1, $bad, $recursive, $good2));
539
        if ($r) {
540
            $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

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

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

627
            $this->assertEquals(4, count(/** @scrutinizer ignore-type */ $r), "wrong number of return values");
Loading history...
628
        }
629
        $this->assertEquals(0, $r[0]->faultCode(), "fault from good1");
630
        if (!$r[0]->faultCode()) {
631
            $val = $r[0]->value();
632
            $this->assertIsString($val, "good1 did not return string");
633
        }
634
        $this->assertNotEquals(0, $r[1]->faultCode(), "no fault from bad");
635
        $this->assertNotEquals(0, $r[2]->faultCode(), "no fault from recursive system.multicall");
636
        $this->assertEquals(0, $r[3]->faultCode(), "fault from good2");
637
        if (!$r[3]->faultCode()) {
638
            $val = $r[3]->value();
639
            $this->assertIsArray($val, "good2 did not return array");
640
        }
641
642
        $this->client->return_type = $returnType;
643
        $this->client->no_multicall = $noMultiCall;
644
    }
645
646
    public function testClientMulticall4()
647
    {
648
        // NB: This test will NOT pass if server does not support system.multicall.
649
650
        $noMultiCall = $this->client->no_multicall;
651
        $returnType = $this->client->return_type;
652
653
        $this->client->return_type = 'xml';
654
        $this->client->no_multicall = false;
655
656
        $good1 = new xmlrpcmsg('system.methodHelp',
657
            array(php_xmlrpc_encode('system.listMethods')));
658
        $good2 = new xmlrpcmsg('system.methodSignature',
659
            array(php_xmlrpc_encode('system.listMethods'))
660
        );
661
662
        $r = $this->send(array($good1, $good2));
663
        if ($r) {
664
            $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

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

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