5784be4dddba9fff6093d57cdd6501a60acff991
[plcapi.git] / test / testsuite.php
1 <?php
2         /* $Id$ */
3
4         include(getcwd().'/parse_args.php');
5
6         require_once('xmlrpc.inc');
7         require_once('xmlrpcs.inc');
8         require_once('xmlrpc_wrappers.inc');
9
10         require_once 'phpunit.php';
11         //require_once 'PHPUnit/TestDecorator.php';
12
13         // let testuite run for the needed time
14         if ((int)ini_get('max_execution_time') < 180)
15                 ini_set('max_execution_time', 180);
16
17         ini_set('max_execution_time', 180);
18
19         $suite = new PHPUnit_TestSuite();
20
21         // array with list of failed tests
22         $failed_tests = array();
23
24         class LocalhostTests extends PHPUnit_TestCase
25         {
26                 var $client = null;
27                 var $method = 'http';
28                 var $timeout = 10;
29                 var $request_compression = null;
30                 var $accepted_compression = '';
31
32                 function fail($message = '')
33                 {
34                         PHPUnit_TestCase::fail($message);
35                         // save in global var that this particular test has failed
36                         // (but only if not called from subclass objects / multitests)
37                         if (function_exists('debug_backtrace') && strtolower(get_class($this)) == 'localhosttests')
38                         {
39                                 global $failed_tests;
40                                 $trace = debug_backtrace();
41                                 for ($i = 0; $i < count($trace); $i++)
42                                 {
43                                         if (strpos($trace[$i]['function'], 'test') === 0)
44                                         {
45                                                 $failed_tests[$trace[$i]['function']] = true;
46                                                 break;
47                                         }
48                                 }
49                         }
50                 }
51
52                 function setUp()
53                 {
54                         global $DEBUG, $LOCALSERVER, $URI;
55                         $server = explode(':', $LOCALSERVER);
56                         if(count($server) > 1)
57                         {
58                                 $this->client=new xmlrpc_client($URI, $server[0], $server[1]);
59                         }
60                         else
61                         {
62                                 $this->client=new xmlrpc_client($URI, $LOCALSERVER);
63                         }
64                         if($DEBUG)
65                         {
66                                 $this->client->setDebug($DEBUG);
67                         }
68                         $this->client->request_compression = $this->request_compression;
69                         $this->client->accepted_compression = $this->accepted_compression;
70                 }
71
72                 function send($msg, $errrorcode=0, $return_response=false)
73                 {
74                         $r = $this->client->send($msg, $this->timeout, $this->method);
75                         // for multicall, return directly array of responses
76                         if(is_array($r))
77                         {
78                                 return $r;
79                         }
80                         $this->assertEquals($r->faultCode(), $errrorcode, 'Error '.$r->faultCode().' connecting to server: '.$r->faultString());
81                         if(!$r->faultCode())
82                         {
83                                 if($return_response)
84                                         return $r;
85                                 else
86                                         return $r->value();
87                         }
88                         else
89                         {
90                                 return null;
91                         }
92                 }
93
94                 function testString()
95                 {
96                         $sendstring="here are 3 \"entities\": < > &" .
97                                 "and here's a dollar sign: \$pretendvarname and a backslash too: " . chr(92) .
98                                 " - isn't that great? \\\"hackery\\\" at it's best " .
99                                 " also don't want to miss out on \$item[0]. ".
100                                 "The real weird stuff follows: CRLF here".chr(13).chr(10).
101                                 "a simple CR here".chr(13).
102                                 "a simple LF here".chr(10).
103                                 "and then LFCR".chr(10).chr(13).
104                                 "last but not least weird names: Günter, Elène, and an xml comment closing tag: -->";
105                         $f=new xmlrpcmsg('examples.stringecho', array(
106                                 new xmlrpcval($sendstring, 'string')
107                         ));
108                         $v=$this->send($f);
109                         if($v)
110                         {
111                                 // when sending/receiving non-US-ASCII encoded strings, XML says cr-lf can be normalized.
112                                 // so we relax our tests...
113                                 $l1 = strlen($sendstring);
114                                 $l2 = strlen($v->scalarval());
115                                 if ($l1 == $l2)
116                                         $this->assertEquals($sendstring, $v->scalarval());
117                                 else
118                                         $this->assertEquals(str_replace(array("\r\n", "\r"), array("\n", "\n"), $sendstring), $v->scalarval());
119                         }
120                 }
121
122                 function testAddingDoubles()
123                 {
124                         // note that rounding errors mean i
125                         // keep precision to sensible levels here ;-)
126                         $a=12.13; $b=-23.98;
127                         $f=new xmlrpcmsg('examples.addtwodouble',array(
128                                 new xmlrpcval($a, 'double'),
129                                 new xmlrpcval($b, 'double')
130                         ));
131                         $v=$this->send($f);
132                         if($v)
133                         {
134                                 $this->assertEquals($a+$b,$v->scalarval());
135                         }
136                 }
137
138                 function testAdding()
139                 {
140                         $f=new xmlrpcmsg('examples.addtwo',array(
141                                 new xmlrpcval(12, 'int'),
142                                 new xmlrpcval(-23, 'int')
143                         ));
144                         $v=$this->send($f);
145                         if($v)
146                         {
147                                 $this->assertEquals(12-23, $v->scalarval());
148                         }
149                 }
150
151                 function testInvalidNumber()
152                 {
153                         $f=new xmlrpcmsg('examples.addtwo',array(
154                                 new xmlrpcval('fred', 'int'),
155                                 new xmlrpcval("\"; exec('ls')", 'int')
156                         ));
157                         $v=$this->send($f);
158                         /// @todo a fault condition should be generated here
159                         /// by the server, which we pick up on
160                         if($v)
161                         {
162                                 $this->assertEquals(0, $v->scalarval());
163                         }
164                 }
165
166                 function testBoolean()
167                 {
168                         $f=new xmlrpcmsg('examples.invertBooleans', array(
169                                 new xmlrpcval(array(
170                                         new xmlrpcval(true, 'boolean'),
171                                         new xmlrpcval(false, 'boolean'),
172                                         new xmlrpcval(1, 'boolean'),
173                                         new xmlrpcval(0, 'boolean'),
174                                         //new xmlrpcval('true', 'boolean'),
175                                         //new xmlrpcval('false', 'boolean')
176                                 ),
177                                 'array'
178                         )));
179                         $answer='0101';
180                         $v=$this->send($f);
181                         if($v)
182                         {
183                                 $sz=$v->arraysize();
184                                 $got='';
185                                 for($i=0; $i<$sz; $i++)
186                                 {
187                                         $b=$v->arraymem($i);
188                                         if($b->scalarval())
189                                         {
190                                                 $got.='1';
191                                         }
192                                         else
193                                         {
194                                                 $got.='0';
195                                         }
196                                 }
197                                 $this->assertEquals($answer, $got);
198                         }
199                 }
200
201                 function testBase64()
202                 {
203                         $sendstring='Mary had a little lamb,
204 Whose fleece was white as snow,
205 And everywhere that Mary went
206 the lamb was sure to go.
207
208 Mary had a little lamb
209 She tied it to a pylon
210 Ten thousand volts went down its back
211 And turned it into nylon';
212                         $f=new xmlrpcmsg('examples.decode64',array(
213                                 new xmlrpcval($sendstring, 'base64')
214                         ));
215                         $v=$this->send($f);
216                         if($v)
217                         {
218                                 if (strlen($sendstring) == strlen($v->scalarval()))
219                                         $this->assertEquals($sendstring, $v->scalarval());
220                                 else
221                                         $this->assertEquals(str_replace(array("\r\n", "\r"), array("\n", "\n"), $sendstring), $v->scalarval());
222                         }
223                 }
224
225                 function testCountEntities()
226                 {
227                         $sendstring = "h'fd>onc>>l>>rw&bpu>q>e<v&gxs<ytjzkami<";
228                         $f = new xmlrpcmsg('validator1.countTheEntities',array(
229                                 new xmlrpcval($sendstring, 'string')
230                         ));
231                         $v = $this->send($f);
232                         if($v)
233                         {
234                                 $got = '';
235                                 $expected = '37210';
236                                 $expect_array = array('ctLeftAngleBrackets','ctRightAngleBrackets','ctAmpersands','ctApostrophes','ctQuotes');
237                                 while(list(,$val) = each($expect_array))
238                                 {
239                                         $b = $v->structmem($val);
240                                         $got .= $b->me['int'];
241                                 }
242                                 $this->assertEquals($expected, $got);
243                         }
244                 }
245
246                 function _multicall_msg($method, $params)
247                 {
248                         $struct['methodName'] = new xmlrpcval($method, 'string');
249                         $struct['params'] = new xmlrpcval($params, 'array');
250                         return new xmlrpcval($struct, 'struct');
251                 }
252
253                 function testServerMulticall()
254                 {
255                         // We manually construct a system.multicall() call to ensure
256                         // that the server supports it.
257
258                         // NB: This test will NOT pass if server does not support system.multicall.
259
260                         // Based on http://xmlrpc-c.sourceforge.net/hacks/test_multicall.py
261                         $good1 = $this->_multicall_msg(
262                                 'system.methodHelp',
263                                 array(php_xmlrpc_encode('system.listMethods')));
264                         $bad = $this->_multicall_msg(
265                                 'test.nosuch',
266                                 array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
267                         $recursive = $this->_multicall_msg(
268                                 'system.multicall',
269                                 array(new xmlrpcval(array(), 'array')));
270                         $good2 = $this->_multicall_msg(
271                                 'system.methodSignature',
272                                 array(php_xmlrpc_encode('system.listMethods')));
273                         $arg = new xmlrpcval(
274                                 array($good1, $bad, $recursive, $good2),
275                                 'array'
276                         );
277
278                         $f = new xmlrpcmsg('system.multicall', array($arg));
279                         $v = $this->send($f);
280                         if($v)
281                         {
282                                 //$this->assertTrue($r->faultCode() == 0, "fault from system.multicall");
283                                 $this->assertTrue($v->arraysize() == 4, "bad number of return values");
284
285                                 $r1 = $v->arraymem(0);
286                                 $this->assertTrue(
287                                         $r1->kindOf() == 'array' && $r1->arraysize() == 1,
288                                         "did not get array of size 1 from good1"
289                                 );
290
291                                 $r2 = $v->arraymem(1);
292                                 $this->assertTrue(
293                                         $r2->kindOf() == 'struct',
294                                         "no fault from bad"
295                                 );
296
297                                 $r3 = $v->arraymem(2);
298                                 $this->assertTrue(
299                                         $r3->kindOf() == 'struct',
300                                         "recursive system.multicall did not fail"
301                                 );
302
303                                 $r4 = $v->arraymem(3);
304                                 $this->assertTrue(
305                                         $r4->kindOf() == 'array' && $r4->arraysize() == 1,
306                                         "did not get array of size 1 from good2"
307                                 );
308                         }
309                 }
310
311                 function testClientMulticall1()
312                 {
313                         // NB: This test will NOT pass if server does not support system.multicall.
314
315                         $this->client->no_multicall = false;
316
317                         $good1 = new xmlrpcmsg('system.methodHelp',
318                                 array(php_xmlrpc_encode('system.listMethods')));
319                         $bad = new xmlrpcmsg('test.nosuch',
320                                 array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
321                         $recursive = new xmlrpcmsg('system.multicall',
322                                 array(new xmlrpcval(array(), 'array')));
323                         $good2 = new xmlrpcmsg('system.methodSignature',
324                                 array(php_xmlrpc_encode('system.listMethods'))
325                         );
326
327                         $r = $this->send(array($good1, $bad, $recursive, $good2));
328                         if($r)
329                         {
330                                 $this->assertTrue(count($r) == 4, "wrong number of return values");
331                         }
332
333                         $this->assertTrue($r[0]->faultCode() == 0, "fault from good1");
334                         if(!$r[0]->faultCode())
335                         {
336                                 $val = $r[0]->value();
337                                 $this->assertTrue(
338                                         $val->kindOf() == 'scalar' && $val->scalartyp() == 'string',
339                                         "good1 did not return string"
340                                 );
341                         }
342                         $this->assertTrue($r[1]->faultCode() != 0, "no fault from bad");
343                         $this->assertTrue($r[2]->faultCode() != 0, "no fault from recursive system.multicall");
344                         $this->assertTrue($r[3]->faultCode() == 0, "fault from good2");
345                         if(!$r[3]->faultCode())
346                         {
347                                 $val = $r[3]->value();
348                                 $this->assertTrue($val->kindOf() == 'array', "good2 did not return array");
349                         }
350                         // This is the only assert in this test which should fail
351                         // if the test server does not support system.multicall.
352                         $this->assertTrue($this->client->no_multicall == false,
353                                 "server does not support system.multicall"
354                         );
355                 }
356
357                 function testClientMulticall2()
358                 {
359                         // NB: This test will NOT pass if server does not support system.multicall.
360
361                         $this->client->no_multicall = true;
362
363                         $good1 = new xmlrpcmsg('system.methodHelp',
364                                 array(php_xmlrpc_encode('system.listMethods')));
365                         $bad = new xmlrpcmsg('test.nosuch',
366                                 array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
367                         $recursive = new xmlrpcmsg('system.multicall',
368                                 array(new xmlrpcval(array(), 'array')));
369                         $good2 = new xmlrpcmsg('system.methodSignature',
370                                 array(php_xmlrpc_encode('system.listMethods'))
371                         );
372
373                         $r = $this->send(array($good1, $bad, $recursive, $good2));
374                         if($r)
375                         {
376                                 $this->assertTrue(count($r) == 4, "wrong number of return values");
377                         }
378
379                         $this->assertTrue($r[0]->faultCode() == 0, "fault from good1");
380                         if(!$r[0]->faultCode())
381                         {
382                                 $val = $r[0]->value();
383                                 $this->assertTrue(
384                                         $val->kindOf() == 'scalar' && $val->scalartyp() == 'string',
385                                         "good1 did not return string");
386                         }
387                         $this->assertTrue($r[1]->faultCode() != 0, "no fault from bad");
388                         $this->assertTrue($r[2]->faultCode() == 0, "fault from (non recursive) system.multicall");
389                         $this->assertTrue($r[3]->faultCode() == 0, "fault from good2");
390                         if(!$r[3]->faultCode())
391                         {
392                                 $val = $r[3]->value();
393                                 $this->assertTrue($val->kindOf() == 'array', "good2 did not return array");
394                         }
395                 }
396
397                 function testClientMulticall3()
398                 {
399                         // NB: This test will NOT pass if server does not support system.multicall.
400
401                         $this->client->return_type = 'phpvals';
402                         $this->client->no_multicall = false;
403
404                         $good1 = new xmlrpcmsg('system.methodHelp',
405                                 array(php_xmlrpc_encode('system.listMethods')));
406                         $bad = new xmlrpcmsg('test.nosuch',
407                                 array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
408                         $recursive = new xmlrpcmsg('system.multicall',
409                                 array(new xmlrpcval(array(), 'array')));
410                         $good2 = new xmlrpcmsg('system.methodSignature',
411                                 array(php_xmlrpc_encode('system.listMethods'))
412                         );
413
414                         $r = $this->send(array($good1, $bad, $recursive, $good2));
415                         if($r)
416                         {
417                                 $this->assertTrue(count($r) == 4, "wrong number of return values");
418                         }
419                         $this->assertTrue($r[0]->faultCode() == 0, "fault from good1");
420                         if(!$r[0]->faultCode())
421                         {
422                                 $val = $r[0]->value();
423                                 $this->assertTrue(
424                                         is_string($val) , "good1 did not return string");
425                         }
426                         $this->assertTrue($r[1]->faultCode() != 0, "no fault from bad");
427                         $this->assertTrue($r[2]->faultCode() != 0, "no fault from recursive system.multicall");
428                         $this->assertTrue($r[3]->faultCode() == 0, "fault from good2");
429                         if(!$r[3]->faultCode())
430                         {
431                                 $val = $r[3]->value();
432                                 $this->assertTrue(is_array($val), "good2 did not return array");
433                         }
434                         $this->client->return_type = 'xmlrpcvals';
435                 }
436
437                 function testCatchWarnings()
438                 {
439                         $f = new xmlrpcmsg('examples.generatePHPWarning', array(
440                                 new xmlrpcval('whatever', 'string')
441                         ));
442                         $v = $this->send($f);
443                         if($v)
444                         {
445                                 $this->assertEquals($v->scalarval(), true);
446                         }
447                 }
448
449                 function testZeroParams()
450                 {
451                         $f = new xmlrpcmsg('system.listMethods');
452                         $v = $this->send($f);
453                 }
454
455                 function testCodeInjectionServerSide()
456                 {
457                         $f = new xmlrpcmsg('system.MethodHelp');
458                         $f->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>";
459                         $v = $this->send($f);
460                         //$v = $r->faultCode();
461                         if ($v)
462                         {
463                                 $this->assertEquals(0, $v->structsize());
464                         }
465                 }
466
467                 function testAutoRegisteredFunction()
468                 {
469                         $f=new xmlrpcmsg('examples.php.getStateName',array(
470                                 new xmlrpcval(23, 'int')
471                         ));
472                         $v=$this->send($f);
473                         if($v)
474                         {
475                                 $this->assertEquals('Michigan', $v->scalarval());
476                         }
477                         else
478                         {
479                                 $this->fail('Note: server can only auto register functions if running with PHP 5.0.3 and up');
480                         }
481                 }
482
483                 function testAutoRegisteredClass()
484                 {
485                         $f=new xmlrpcmsg('examples.php2.getStateName',array(
486                                 new xmlrpcval(23, 'int')
487                         ));
488                         $v=$this->send($f);
489                         if($v)
490                         {
491                                 $this->assertEquals('Michigan', $v->scalarval());
492                         $f=new xmlrpcmsg('examples.php3.getStateName',array(
493                                 new xmlrpcval(23, 'int')
494                         ));
495                         $v=$this->send($f);
496                         if($v)
497                         {
498                                 $this->assertEquals('Michigan', $v->scalarval());
499                         }
500                 }
501                         else
502                         {
503                                 $this->fail('Note: server can only auto register class methods if running with PHP 5.0.3 and up');
504                         }
505                 }
506
507                 function testAutoRegisteredMethod()
508                 {
509                         $func=wrap_xmlrpc_method($this->client, 'examples.getStateName');
510                         if($func == '')
511                         {
512                                 $this->fail('Registration of examples.getStateName failed');
513                         }
514                         else
515                         {
516                                 $v=$func(23);
517                                 $this->assertEquals('Michigan', $v);
518                         }
519                 }
520
521                 function testGetCookies()
522                 {
523                         // let server set to us some cookies we tell it
524                         $cookies = array(
525                                 //'c1' => array(),
526                                 'c2' => array('value' => 'c2'),
527                                 'c3' => array('value' => 'c3', 'expires' => time()+60*60*24*30),
528                                 'c4' => array('value' => 'c4', 'expires' => time()+60*60*24*30, 'path' => '/'),
529                                 'c5' => array('value' => 'c5', 'expires' => time()+60*60*24*30, 'path' => '/', 'domain' => 'localhost'),
530                         );
531                         $cookiesval =& php_xmlrpc_encode($cookies);
532                         $f=new xmlrpcmsg('examples.setcookies',array($cookiesval));
533                         $r=$this->send($f, 0, true);
534                         if($r)
535                         {
536                                 $v = $r->value();
537                                 $this->assertEquals(1, $v->scalarval());
538                                 // now check if we decoded the cookies as we had set them
539                                 $rcookies = $r->cookies();
540                                 foreach($cookies as $c => $v)
541                                 // format for date string in cookies: 'Mon, 31 Oct 2005 13:50:56 GMT'
542                                 // but PHP versions differ on that, some use 'Mon, 31-Oct-2005 13:50:56 GMT'...
543                                         if(isset($v['expires']))
544                                         {
545                                                 if (isset($rcookies[$c]['expires']) && strpos($rcookies[$c]['expires'], '-'))
546                                                 {
547                                                         $cookies[$c]['expires'] = gmdate('D, d\-M\-Y H:i:s \G\M\T' ,$cookies[$c]['expires']);
548                                                 }
549                                                 else
550                                                 {
551                                                         $cookies[$c]['expires'] = gmdate('D, d M Y H:i:s \G\M\T' ,$cookies[$c]['expires']);
552                                                 }
553                                         }
554                                 $this->assertEquals($cookies, $rcookies);
555                         }
556                 }
557
558                 function testSetCookies()
559                 {
560                         // let server set to us some cookies we tell it
561                         $cookies = array(
562                                 'c0' => null,
563                                 'c1' => 1,
564                                 'c2' => '2 3',
565                                 'c3' => '!@#$%^&*()_+|}{":?><,./\';[]\\=-'
566                         );
567                         $f=new xmlrpcmsg('examples.getcookies',array());
568                         foreach ($cookies as $cookie => $val)
569                         {
570                                 $this->client->setCookie($cookie, $val);
571                                 $cookies[$cookie] = (string) $cookies[$cookie];
572                         }
573                         $r = $this->client->send($f, $this->timeout, $this->method);
574                         $this->assertEquals($r->faultCode(), 0, 'Error '.$r->faultCode().' connecting to server: '.$r->faultString());
575                         if(!$r->faultCode())
576                         {
577                                 $v = $r->value();
578                                 $v = php_xmlrpc_decode($v);
579                                 // on IIS and Apache getallheaders returns something slightly different...
580                                 $this->assertEquals($v, $cookies);
581                         }
582                 }
583
584                 function testSendTwiceSameMsg()
585                 {
586                         $f=new xmlrpcmsg('examples.stringecho', array(
587                                 new xmlrpcval('hello world', 'string')
588                         ));
589                         $v1 = $this->send($f);
590                         $v2 = $this->send($f);
591                         //$v = $r->faultCode();
592                         if ($v1 && $v2)
593                         {
594                                 $this->assertEquals($v2, $v1);
595                         }
596                 }
597         }
598
599         class LocalHostMultiTests extends LocalhostTests
600         {
601                 function _runtests()
602                 {
603                         global $failed_tests;
604                         foreach(get_class_methods('LocalhostTests') as $meth)
605                         {
606                                 if(strpos($meth, 'test') === 0 && $meth != 'testHttps')
607                                 {
608                                         if (!isset($failed_tests[$meth]))
609                                                 $this->$meth();
610                                 }
611                                 if ($this->_failed)
612                                 {
613                                         break;
614                                 }
615                         }
616                 }
617
618                 function testDeflate()
619                 {
620                         if(!function_exists('gzdeflate'))
621                         {
622                                 $this->fail('Zlib missing: cannot test deflate functionality');
623                                 return;
624                         }
625                         $this->client->accepted_compression = array('deflate');
626                         $this->client->request_compression = 'deflate';
627                         $this->_runtests();
628                 }
629
630                 function testGzip()
631                 {
632                         if(!function_exists('gzdeflate'))
633                         {
634                                 $this->fail('Zlib missing: cannot test gzip functionality');
635                                 return;
636                         }
637                         $this->client->accepted_compression = array('gzip');
638                         $this->client->request_compression = 'gzip';
639                         $this->_runtests();
640                 }
641
642                 function testKeepAlives()
643                 {
644                         if(!function_exists('curl_init'))
645                         {
646                                 $this->fail('CURL missing: cannot test http 1.1');
647                                 return;
648                         }
649                         $this->method = 'http11';
650                         $this->client->keepalive = true;
651                         $this->_runtests();
652                 }
653
654                 function testProxy()
655                 {
656                         global $PROXYSERVER, $PROXYPORT;
657             if ($PROXYSERVER)
658             {
659                                 $this->client->setProxy($PROXYSERVER, $PROXYPORT);
660                                 $this->_runtests();
661             }
662             else
663                 $this->fail('PROXY definition missing: cannot test proxy');
664                 }
665
666                 function testHttp11()
667                 {
668                         if(!function_exists('curl_init'))
669                         {
670                                 $this->fail('CURL missing: cannot test http 1.1');
671                                 return;
672                         }
673                         $this->method = 'http11'; // not an error the double assignment!
674                         $this->client->method = 'http11';
675                         //$this->client->verifyhost = 0;
676                         //$this->client->verifypeer = 0;
677                         $this->client->keepalive = false;
678                         $this->_runtests();
679                 }
680
681                 function testHttp11Gzip()
682                 {
683                         if(!function_exists('curl_init'))
684                         {
685                                 $this->fail('CURL missing: cannot test http 1.1');
686                                 return;
687                         }
688                         $this->method = 'http11'; // not an error the double assignment!
689                         $this->client->method = 'http11';
690                         $this->client->keepalive = false;
691                         $this->client->accepted_compression = array('gzip');
692                         $this->client->request_compression = 'gzip';
693                         $this->_runtests();
694                 }
695
696                 function testHttp11Deflate()
697                 {
698                         if(!function_exists('curl_init'))
699                         {
700                                 $this->fail('CURL missing: cannot test http 1.1');
701                                 return;
702                         }
703                         $this->method = 'http11'; // not an error the double assignment!
704                         $this->client->method = 'http11';
705                         $this->client->keepalive = false;
706                         $this->client->accepted_compression = array('deflate');
707                         $this->client->request_compression = 'deflate';
708                         $this->_runtests();
709                 }
710
711                 function testHttp11Proxy()
712                 {
713                         global $PROXYSERVER, $PROXYPORT;
714                         if(!function_exists('curl_init'))
715                         {
716                                 $this->fail('CURL missing: cannot test http 1.1 w. proxy');
717                                 return;
718                         }
719             else if ($PROXYSERVER == '')
720             {
721                 $this->fail('PROXY definition missing: cannot test proxy w. http 1.1');
722                 return;
723             }
724                         $this->method = 'http11'; // not an error the double assignment!
725                         $this->client->method = 'http11';
726             $this->client->setProxy($PROXYSERVER, $PROXYPORT);
727                         //$this->client->verifyhost = 0;
728                         //$this->client->verifypeer = 0;
729                         $this->client->keepalive = false;
730                         $this->_runtests();
731                 }
732
733                 function testHttps()
734                 {
735                         global $HTTPSSERVER, $HTTPSURI;
736                         if(!function_exists('curl_init'))
737                         {
738                                 $this->fail('CURL missing: cannot test https functionality');
739                                 return;
740                         }
741                         $this->client->server = $HTTPSSERVER;
742                         $this->method = 'https';
743                         $this->client->method = 'https';
744                         $this->client->path = $HTTPSURI;
745                         $this->_runtests();
746                 }
747
748                 function testHttpsProxy()
749                 {
750                         global $HTTPSSERVER, $HTTPSURI, $PROXYSERVER, $PROXYPORT;;
751                         if(!function_exists('curl_init'))
752                         {
753                                 $this->fail('CURL missing: cannot test https functionality');
754                                 return;
755                         }
756             else if ($PROXYSERVER == '')
757             {
758                 $this->fail('PROXY definition missing: cannot test proxy w. http 1.1');
759                 return;
760             }
761                         $this->client->server = $HTTPSSERVER;
762                         $this->method = 'https';
763                         $this->client->method = 'https';
764             $this->client->setProxy($PROXYSERVER, $PROXYPORT);
765                         $this->client->path = $HTTPSURI;
766                         $this->_runtests();
767                 }
768
769                 function testUTF8Responses()
770                 {
771                         global $URI;
772                         //$this->client->path = strpos($URI, '?') === null ? $URI.'?RESPONSE_ENCODING=UTF-8' : $URI.'&RESPONSE_ENCODING=UTF-8';
773                         $this->client->path = $URI.'?RESPONSE_ENCODING=UTF-8';
774                         $this->_runtests();
775                 }
776
777                 function testUTF8Requests()
778                 {
779                         $this->client->request_charset_encoding = 'UTF-8';
780                         $this->_runtests();
781                 }
782
783                 function testISOResponses()
784                 {
785                         global $URI;
786                         //$this->client->path = strpos($URI, '?') === null ? $URI.'?RESPONSE_ENCODING=UTF-8' : $URI.'&RESPONSE_ENCODING=UTF-8';
787                         $this->client->path = $URI.'?RESPONSE_ENCODING=ISO-8859-1';
788                         $this->_runtests();
789                 }
790
791                 function testISORequests()
792                 {
793                         $this->client->request_charset_encoding = 'ISO-8859-1';
794                         $this->_runtests();
795                 }
796         }
797
798         class ParsingBugsTests extends PHPUnit_TestCase
799         {
800                 function testMinusOneString()
801                 {
802                         $v=new xmlrpcval('-1');
803                         $u=new xmlrpcval('-1', 'string');
804                         $this->assertEquals($u->scalarval(), $v->scalarval());
805                 }
806
807                 function testUnicodeInMemberName(){
808                         $v = array('Günter, Elène' => new xmlrpcval(1));
809                         $r = new xmlrpcresp(new xmlrpcval($v, 'struct'));
810                         $r = $r->serialize();
811                         $m = new xmlrpcmsg('dummy');
812                         $r = $m->parseResponse($r);
813                         $v = $r->value();
814                         $this->assertEquals($v->structmemexists('Günter, Elène'), true);
815                 }
816
817                 function testUnicodeInErrorString()
818                 {
819                         $response = utf8_encode(
820 '<?xml version="1.0"?>
821 <!-- $Id -->
822 <!-- found by G. giunta, covers what happens when lib receives
823   UTF8 chars in reponse text and comments -->
824 <!-- àüè&#224;&#252;&#232; -->
825 <methodResponse>
826 <fault>
827 <value>
828 <struct>
829 <member>
830 <name>faultCode</name>
831 <value><int>888</int></value>
832 </member>
833 <member>
834 <name>faultString</name>
835 <value><string>àüè&#224;&#252;&#232;</string></value>
836 </member>
837 </struct>
838 </value>
839 </fault>
840 </methodResponse>');
841                         $m=new xmlrpcmsg('dummy');
842                         $r=$m->parseResponse($response);
843                         $v=$r->faultString();
844                         $this->assertEquals('àüèàüè', $v);
845                 }
846
847                 function testValidNumbers()
848                 {
849                         $m=new xmlrpcmsg('dummy');
850                         $fp=
851 '<?xml version="1.0"?>
852 <methodResponse>
853 <params>
854 <param>
855 <value>
856 <struct>
857 <member>
858 <name>integer1</name>
859 <value><int>01</int></value>
860 </member>
861 <member>
862 <name>float1</name>
863 <value><double>01.10</double></value>
864 </member>
865 <member>
866 <name>integer2</name>
867 <value><int>+1</int></value>
868 </member>
869 <member>
870 <name>float2</name>
871 <value><double>+1.10</double></value>
872 </member>
873 <member>
874 <name>float3</name>
875 <value><double>-1.10e2</double></value>
876 </member>
877 </struct>
878 </value>
879 </param>
880 </params>
881 </methodResponse>';
882                         $r=$m->parseResponse($fp);
883                         $v=$r->value();
884                         $s=$v->structmem('integer1');
885                         $t=$v->structmem('float1');
886                         $u=$v->structmem('integer2');
887                         $w=$v->structmem('float2');
888                         $x=$v->structmem('float3');
889                         $this->assertEquals(1, $s->scalarval());
890                         $this->assertEquals(1.1, $t->scalarval());
891                         $this->assertEquals(1, $u->scalarval());
892                         $this->assertEquals(1.1, $w->scalarval());
893                         $this->assertEquals(-110.0, $x->scalarval());
894                 }
895
896                 function testAddScalarToStruct()
897                 {
898                         $v=new xmlrpcval(array('a' => 'b'), 'struct');
899                         // use @ operator in case error_log gets on screen
900                         $r= @$v->addscalar('c');
901                         $this->assertEquals(0, $r);
902                 }
903
904                 function testAddStructToStruct()
905                 {
906                         $v=new xmlrpcval(array('a' => new xmlrpcval('b')), 'struct');
907                         $r=$v->addstruct(array('b' => new xmlrpcval('c')));
908                         $this->assertEquals(2, $v->structsize());
909                         $this->assertEquals(1, $r);
910                         $r=$v->addstruct(array('b' => new xmlrpcval('b')));
911                         $this->assertEquals(2, $v->structsize());
912                 }
913
914                 function testAddArrayToArray()
915                 {
916                         $v=new xmlrpcval(array(new xmlrpcval('a'), new xmlrpcval('b')), 'array');
917                         $r=$v->addarray(array(new xmlrpcval('b'), new xmlrpcval('c')));
918                         $this->assertEquals(4, $v->arraysize());
919                         $this->assertEquals(1, $r);
920                 }
921
922                 function testEncodeArray()
923                 {
924                         $r=range(1, 100);
925                         $v = php_xmlrpc_encode($r);
926                         $this->assertEquals('array', $v->kindof());
927                 }
928
929                 function testEncodeRecursive()
930                 {
931                         $v = php_xmlrpc_encode(php_xmlrpc_encode('a simple string'));
932                         $this->assertEquals('scalar', $v->kindof());
933                 }
934
935                 function testBrokenRequests()
936                 {
937                         $s = new xmlrpc_server();
938 // omitting the 'params' tag: not tolerated by the lib anymore
939 $f = '<?xml version="1.0"?>
940 <methodCall>
941 <methodName>system.methodHelp</methodName>
942 <param>
943 <value><string>system.methodHelp</string></value>
944 </param>
945 </methodCall>';
946                         $r = $s->parserequest($f);
947                         $this->assertEquals(15, $r->faultCode());
948 // omitting a 'param' tag
949 $f = '<?xml version="1.0"?>
950 <methodCall>
951 <methodName>system.methodHelp</methodName>
952 <params>
953 <value><string>system.methodHelp</string></value>
954 </params>
955 </methodCall>';
956                         $r = $s->parserequest($f);
957                         $this->assertEquals(15, $r->faultCode());
958 // omitting a 'value' tag
959 $f = '<?xml version="1.0"?>
960 <methodCall>
961 <methodName>system.methodHelp</methodName>
962 <params>
963 <param><string>system.methodHelp</string></param>
964 </params>
965 </methodCall>';
966                         $r = $s->parserequest($f);
967                         $this->assertEquals(15, $r->faultCode());
968                 }
969
970                 function testBrokenResponses()
971                 {
972                         $m=new xmlrpcmsg('dummy');
973                         //$m->debug = 1;
974 // omitting the 'params' tag: no more tolerated by the lib...
975 $f = '<?xml version="1.0"?>
976 <methodResponse>
977 <param>
978 <value><string>system.methodHelp</string></value>
979 </param>
980 </methodResponse>';
981                         $r = $m->parseResponse($f);
982                         $this->assertEquals(2, $r->faultCode());
983 // omitting the 'param' tag: no more tolerated by the lib...
984 $f = '<?xml version="1.0"?>
985 <methodResponse>
986 <params>
987 <value><string>system.methodHelp</string></value>
988 </params>
989 </methodResponse>';
990                         $r = $m->parseResponse($f);
991                         $this->assertEquals(2, $r->faultCode());
992 // omitting a 'value' tag: KO
993 $f = '<?xml version="1.0"?>
994 <methodResponse>
995 <params>
996 <param><string>system.methodHelp</string></param>
997 </params>
998 </methodResponse>';
999                         $r = $m->parseResponse($f);
1000                         $this->assertEquals(2, $r->faultCode());
1001                 }
1002
1003                 function testBuggyHttp()
1004                 {
1005                         $s = new xmlrpcmsg('dummy');
1006 $f = 'HTTP/1.1 100 Welcome to the jungle
1007
1008 HTTP/1.0 200 OK
1009 X-Content-Marx-Brothers: Harpo
1010                         Chico and Groucho
1011 Content-Length: who knows?
1012
1013
1014
1015 <?xml version="1.0"?>
1016 <!-- First of all, let\'s check out if the lib properly handles a commented </methodResponse> tag... -->
1017 <methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
1018 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
1019
1020
1021 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
1022 <script type="text\javascript">document.write(\'Hello, my name is added nag, I\\\'m happy to serve your content for free\');</script>
1023  ';
1024                         $r = $s->parseResponse($f);
1025                         $v = $r->value();
1026                         $s = $v->structmem('content');
1027                         $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s->scalarval());
1028                 }
1029
1030                 function testStringBug()
1031                 {
1032                         $s = new xmlrpcmsg('dummy');
1033 $f = '<?xml version="1.0"?>
1034 <!-- $Id -->
1035 <!-- found by 2z69xks7bpy001@sneakemail.com, amongst others
1036  covers what happens when there\'s character data after </string>
1037  and before </value> -->
1038 <methodResponse>
1039 <params>
1040 <param>
1041 <value>
1042 <struct>
1043 <member>
1044 <name>success</name>
1045 <value>
1046 <boolean>1</boolean>
1047 </value>
1048 </member>
1049 <member>
1050 <name>sessionID</name>
1051 <value>
1052 <string>S300510007I</string>
1053 </value>
1054 </member>
1055 </struct>
1056 </value>
1057 </param>
1058 </params>
1059 </methodResponse> ';
1060                         $r = $s->parseResponse($f);
1061                         $v = $r->value();
1062                         $s = $v->structmem('sessionID');
1063                         $this->assertEquals('S300510007I', $s->scalarval());
1064                 }
1065
1066                 function testWhiteSpace()
1067                 {
1068                         $s = new xmlrpcmsg('dummy');
1069 $f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
1070 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
1071
1072
1073 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
1074 ';
1075                         $r = $s->parseResponse($f);
1076                         $v = $r->value();
1077                         $s = $v->structmem('content');
1078                         $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s->scalarval());
1079                 }
1080
1081                 function testDoubleDataInArrayTag()
1082                 {
1083                         $s = new xmlrpcmsg('dummy');
1084 $f = '<?xml version="1.0"?><methodResponse><params><param><value><array>
1085 <data></data>
1086 <data></data>
1087 </array></value></param></params></methodResponse>
1088 ';
1089                         $r = $s->parseResponse($f);
1090                         $v = $r->faultCode();
1091                         $this->assertEquals(2, $v);
1092 $f = '<?xml version="1.0"?><methodResponse><params><param><value><array>
1093 <data><value>Hello world</value></data>
1094 <data></data>
1095 </array></value></param></params></methodResponse>
1096 ';
1097                         $r = $s->parseResponse($f);
1098                         $v = $r->faultCode();
1099                         $this->assertEquals(2, $v);
1100                 }
1101
1102                 function testDoubleStuffInValueTag()
1103                 {
1104                         $s = new xmlrpcmsg('dummy');
1105 $f = '<?xml version="1.0"?><methodResponse><params><param><value>
1106 <string>hello world</string>
1107 <array><data></data></array>
1108 </value></param></params></methodResponse>
1109 ';
1110                         $r = $s->parseResponse($f);
1111                         $v = $r->faultCode();
1112                         $this->assertEquals(2, $v);
1113 $f = '<?xml version="1.0"?><methodResponse><params><param><value>
1114 <string>hello</string>
1115 <string>world</string>
1116 </value></param></params></methodResponse>
1117 ';
1118                         $r = $s->parseResponse($f);
1119                         $v = $r->faultCode();
1120                         $this->assertEquals(2, $v);
1121 $f = '<?xml version="1.0"?><methodResponse><params><param><value>
1122 <string>hello</string>
1123 <struct><member><name>hello><value>world</value></member></struct>
1124 </value></param></params></methodResponse>
1125 ';
1126                         $r = $s->parseResponse($f);
1127                         $v = $r->faultCode();
1128                         $this->assertEquals(2, $v);
1129                 }
1130
1131                 function testAutodecodeResponse()
1132                 {
1133                         $s = new xmlrpcmsg('dummy');
1134 $f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
1135 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
1136
1137
1138 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
1139 ';
1140                         $r = $s->parseResponse($f, true, 'phpvals');
1141                         $v = $r->value();
1142                         $s = $v['content'];
1143                         $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s);
1144                 }
1145
1146                 function testNoDecodeResponse()
1147                 {
1148                         $s = new xmlrpcmsg('dummy');
1149 $f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
1150 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
1151
1152
1153 and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>';
1154                         $r = $s->parseResponse($f, true, 'xml');
1155                         $v = $r->value();
1156                         $this->assertEquals($f, $v);
1157                 }
1158
1159                 function testAutoCoDec()
1160                 {
1161                         $data1 = array(1, 1.0, 'hello world', true, '20051021T23:43:00', -1, 11.0, '~!@#$%^&*()_+|', false, '20051021T23:43:00');
1162                         $data2 = array('zero' => $data1, 'one' => $data1, 'two' => $data1, 'three' => $data1, 'four' => $data1, 'five' => $data1, 'six' => $data1, 'seven' => $data1, 'eight' => $data1, 'nine' => $data1);
1163                         $data = array($data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2);
1164                         //$keys = array('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
1165                         $v1 = php_xmlrpc_encode($data, array('auto_dates'));
1166                         $v2 = php_xmlrpc_decode_xml($v1->serialize());
1167                         $this->assertEquals($v1, $v2);
1168                         $r1 = new xmlrpcresp($v1);
1169                         $r2 = php_xmlrpc_decode_xml($r1->serialize());
1170                         $r2->serialize(); // needed to set internal member payload
1171                         $this->assertEquals($r1, $r2);
1172                         $m1 = new xmlrpcmsg('hello dolly', array($v1));
1173                         $m2 = php_xmlrpc_decode_xml($m1->serialize());
1174                         $m2->serialize(); // needed to set internal member payload
1175                         $this->assertEquals($m1, $m2);
1176                 }
1177
1178                 function testUTF8Request()
1179                 {
1180                         $sendstring='κόσμε'; // Greek word 'kosme'. NB: NOT a valid ISO8859 string!
1181                         $GLOBALS['xmlrpc_internalencoding'] = 'UTF-8';
1182                         $f = new xmlrpcval($sendstring, 'string');
1183                         $v=$f->serialize();
1184                         $this->assertEquals("<value><string>&#954;&#8057;&#963;&#956;&#949;</string></value>\n", $v);
1185                         $GLOBALS['xmlrpc_internalencoding'] = 'ISO-8859-1';
1186                 }
1187
1188                 function testUTF8Response()
1189                 {
1190                         $s = new xmlrpcmsg('dummy');
1191 $f = "HTTP/1.1 200 OK\r\nContent-type: text/xml; charset=UTF-8\r\n\r\n".'<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
1192 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>'.utf8_encode('àüèàüè').'</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
1193 ';
1194                         $r = $s->parseResponse($f, false, 'phpvals');
1195                         $v = $r->value();
1196                         $v = $v['content'];
1197                         $this->assertEquals("àüèàüè", $v);
1198 $f = '<?xml version="1.0" encoding="utf-8"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
1199 <member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>'.utf8_encode('àüèàüè').'</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
1200 ';
1201                         $r = $s->parseResponse($f, false, 'phpvals');
1202                         $v = $r->value();
1203                         $v = $v['content'];
1204                         $this->assertEquals("àüèàüè", $v);
1205                 }
1206
1207                 function testUTF8IntString()
1208                 {
1209                         $v=new xmlrpcval(100, 'int');
1210                         $s=$v->serialize('UTF-8');
1211                         $this->assertequals("<value><int>100</int></value>\n", $s);
1212                 }
1213
1214                 function testStringInt()
1215                 {
1216                         $v=new xmlrpcval('hello world', 'int');
1217                         $s=$v->serialize();
1218                         $this->assertequals("<value><int>0</int></value>\n", $s);
1219                 }
1220
1221                 function testStructMemExists()
1222                 {
1223                         $v=php_xmlrpc_encode(array('hello' => 'world'));
1224                         $b=$v->structmemexists('hello');
1225                         $this->assertequals(true, $b);
1226                         $b=$v->structmemexists('world');
1227                         $this->assertequals(false, $b);
1228                 }
1229
1230                 function testNilvalue()
1231                 {
1232                         // default case: we do not accept nil values received
1233                         $v = new xmlrpcval('hello', 'null');
1234                         $r = new xmlrpcresp($v);
1235                         $s = $r->serialize();
1236                         $m = new xmlrpcmsg('dummy');
1237                         $r = $m->parseresponse($s);
1238                         $this->assertequals(2, $r->faultCode());
1239                         // enable reception of nil values
1240                         $GLOBALS['xmlrpc_null_extension'] = true;
1241                         $r = $m->parseresponse($s);
1242                         $v = $r->value();
1243                         $this->assertequals('null', $v->scalartyp());
1244                 }
1245
1246                 function TestLocale()
1247         {
1248             $locale = setlocale(LC_NUMERIC,0);
1249             if ( setlocale(LC_NUMERIC,'deu', 'de_DE@euro', 'de_DE', 'de', 'ge') !== false )
1250             {
1251                         $v = new xmlrpcval(1.1,'double');
1252                         $r = $v->serialize();
1253                         $this->assertequals(false, strpos($r,','));
1254                         $this->assertequals(1, strpos($v->scalarval(),','));
1255                         setlocale(LC_NUMERIC,$locale);
1256                 }
1257                 }
1258         }
1259
1260         class InvalidHostTests extends PHPUnit_TestCase
1261         {
1262                 var $client = null;
1263
1264                 function setUp()
1265                 {
1266                         global $DEBUG,$LOCALSERVER;
1267                         $this->client=new xmlrpc_client('/NOTEXIST.php', $LOCALSERVER, 80);
1268                         if($DEBUG)
1269                         {
1270                                 $this->client->setDebug($DEBUG);
1271                         }
1272                 }
1273
1274                 function test404()
1275                 {
1276                         $f = new xmlrpcmsg('examples.echo',array(
1277                                 new xmlrpcval('hello', 'string')
1278                         ));
1279                         $r = $this->client->send($f, 5);
1280                         $this->assertEquals(5, $r->faultCode());
1281                 }
1282
1283                 function testSrvNotFound()
1284                 {
1285                         $f = new xmlrpcmsg('examples.echo',array(
1286                                 new xmlrpcval('hello', 'string')
1287                         ));
1288                         $this->client->server .= 'XXX';
1289                         $r = $this->client->send($f, 5);
1290                         $this->assertEquals(5, $r->faultCode());
1291                 }
1292
1293                 function testCurlKAErr()
1294                 {
1295                         global $LOCALSERVER, $URI;
1296                         if(!function_exists('curl_init'))
1297                         {
1298                                 $this->fail('CURL missing: cannot test curl keepalive errors');
1299                                 return;
1300                         }
1301                         $f = new xmlrpcmsg('examples.stringecho',array(
1302                                 new xmlrpcval('hello', 'string')
1303                         ));
1304                         // test 2 calls w. keepalive: 1st time connection ko, second time ok
1305                         $this->client->server .= 'XXX';
1306                         $this->client->keepalive = true;
1307                         $r = $this->client->send($f, 5, 'http11');
1308                         $this->assertEquals(8, $r->faultCode());
1309
1310                         // now test a successful connection
1311                         $server = explode(':', $LOCALSERVER);
1312                         if(count($server) > 1)
1313                         {
1314                                 $this->client->port = $server[1];
1315                         }
1316                         $this->client->server = $server[0];
1317                         $this->client->path = $URI;
1318
1319                         $r = $this->client->send($f, 5, 'http11');
1320                         $r = $r->value();
1321                         $this->assertEquals('hello', $r->scalarVal());
1322                 }
1323         }
1324
1325
1326         $suite->addTest(new LocalhostTests('testString'));
1327         $suite->addTest(new LocalhostTests('testAdding'));
1328         $suite->addTest(new LocalhostTests('testAddingDoubles'));
1329         $suite->addTest(new LocalhostTests('testInvalidNumber'));
1330         $suite->addTest(new LocalhostTests('testBoolean'));
1331         $suite->addTest(new LocalhostTests('testCountEntities'));
1332         $suite->addTest(new LocalhostTests('testBase64'));
1333         $suite->addTest(new LocalhostTests('testServerMulticall'));
1334         $suite->addTest(new LocalhostTests('testClientMulticall1'));
1335         $suite->addTest(new LocalhostTests('testClientMulticall2'));
1336         $suite->addTest(new LocalhostTests('testClientMulticall3'));
1337         $suite->addTest(new LocalhostTests('testCatchWarnings'));
1338         $suite->addTest(new LocalhostTests('testZeroParams'));
1339         $suite->addTest(new LocalhostTests('testCodeInjectionServerSide'));
1340         $suite->addTest(new LocalhostTests('testAutoRegisteredFunction'));
1341         $suite->addTest(new LocalhostTests('testAutoRegisteredMethod'));
1342         $suite->addTest(new LocalhostTests('testSetCookies'));
1343         $suite->addTest(new LocalhostTests('testGetCookies'));
1344         $suite->addTest(new LocalhostTests('testSendTwiceSameMsg'));
1345
1346         $suite->addTest(new LocalhostMultiTests('testUTF8Requests'));
1347         $suite->addTest(new LocalhostMultiTests('testUTF8Responses'));
1348         $suite->addTest(new LocalhostMultiTests('testISORequests'));
1349         $suite->addTest(new LocalhostMultiTests('testISOResponses'));
1350         $suite->addTest(new LocalhostMultiTests('testGzip'));
1351         $suite->addTest(new LocalhostMultiTests('testDeflate'));
1352         $suite->addTest(new LocalhostMultiTests('testProxy'));
1353         $suite->addTest(new LocalhostMultiTests('testHttp11'));
1354         $suite->addTest(new LocalhostMultiTests('testHttp11Gzip'));
1355         $suite->addTest(new LocalhostMultiTests('testHttp11Deflate'));
1356         $suite->addTest(new LocalhostMultiTests('testKeepAlives'));
1357         $suite->addTest(new LocalhostMultiTests('testHttp11Proxy'));
1358         $suite->addTest(new LocalhostMultiTests('testHttps'));
1359         $suite->addTest(new LocalhostMultiTests('testHttpsProxy'));
1360
1361         $suite->addTest(new InvalidHostTests('test404'));
1362         //$suite->addTest(new InvalidHostTests('testSrvNotFound'));
1363         $suite->addTest(new InvalidHostTests('testCurlKAErr'));
1364
1365         $suite->addTest(new ParsingBugsTests('testMinusOneString'));
1366         $suite->addTest(new ParsingBugsTests('testUnicodeInMemberName'));
1367         $suite->addTest(new ParsingBugsTests('testUnicodeInErrorString'));
1368         $suite->addTest(new ParsingBugsTests('testValidNumbers'));
1369         $suite->addTest(new ParsingBugsTests('testAddScalarToStruct'));
1370         $suite->addTest(new ParsingBugsTests('testAddStructToStruct'));
1371         $suite->addTest(new ParsingBugsTests('testAddArrayToArray'));
1372         $suite->addTest(new ParsingBugsTests('testEncodeArray'));
1373         $suite->addTest(new ParsingBugsTests('testEncodeRecursive'));
1374         $suite->addTest(new ParsingBugsTests('testBrokenrequests'));
1375         $suite->addTest(new ParsingBugsTests('testBrokenresponses'));
1376         $suite->addTest(new ParsingBugsTests('testBuggyHttp'));
1377         $suite->addTest(new ParsingBugsTests('testStringBug'));
1378         $suite->addTest(new ParsingBugsTests('testWhiteSpace'));
1379         $suite->addTest(new ParsingBugsTests('testAutodecodeResponse'));
1380         $suite->addTest(new ParsingBugsTests('testNoDecodeResponse'));
1381         $suite->addTest(new ParsingBugsTests('testAutoCoDec'));
1382         $suite->addTest(new ParsingBugsTests('testUTF8Response'));
1383         $suite->addTest(new ParsingBugsTests('testUTF8Request'));
1384         $suite->addTest(new ParsingBugsTests('testUTF8IntString'));
1385         $suite->addTest(new ParsingBugsTests('testStringInt'));
1386         $suite->addTest(new ParsingBugsTests('testStructMemExists'));
1387         $suite->addTest(new ParsingBugsTests('testDoubleDataInArrayTag'));
1388         $suite->addTest(new ParsingBugsTests('testDoubleStuffInValueTag'));
1389         $suite->addTest(new ParsingBugsTests('testNilValue'));
1390         $suite->addTest(new ParsingBugsTests('testLocale'));
1391
1392         $title = 'XML-RPC Unit Tests';
1393
1394         if(isset($only))
1395         {
1396                 $suite = new PHPUnit_TestSuite($only);
1397         }
1398
1399         if(isset($_SERVER['REQUEST_METHOD']))
1400         {
1401                 echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">\n<head>\n<title>$title</title>\n</head>\n<body>\n<h1>$title</h1>\n";
1402         }
1403         else
1404         {
1405                 echo "$title\n\n";
1406         }
1407
1408         if(isset($_SERVER['REQUEST_METHOD']))
1409         {
1410                 echo "<h3>Using lib version: $xmlrpcVersion on PHP version: ".phpversion()."</h3>\n";
1411                 echo '<h3>Running '.$suite->testCount().' tests (some of which are multiple) against servers: http://'.htmlspecialchars($LOCALSERVER.$URI).' and https://'.htmlspecialchars($HTTPSSERVER.$HTTPSURI)."\n ...</h3>\n";
1412                 flush();
1413             ob_flush();
1414         }
1415         else
1416         {
1417                 echo "Using lib version: $xmlrpcVersion on PHP version: ".phpversion()."\n";
1418                 echo 'Running '.$suite->testCount().' tests (some of which are multiple) against servers: http://'.$LOCALSERVER.$URI.' and https://'.$HTTPSSERVER.$HTTPSURI."\n\n";
1419         }
1420
1421         // do some basic timing measurement
1422         list($micro, $sec) = explode(' ', microtime());
1423         $start_time = $sec + $micro;
1424
1425         $PHPUnit = new PHPUnit;
1426         $result = $PHPUnit->run($suite, ($DEBUG == 0 ? '.' : '<hr/>'));
1427
1428         list($micro, $sec) = explode(' ', microtime());
1429         $end_time = $sec + $micro;
1430
1431         if(!isset($_SERVER['REQUEST_METHOD']))
1432         {
1433                 echo $result->toString()."\n";
1434         }
1435
1436         if(isset($_SERVER['REQUEST_METHOD']))
1437         {
1438                 echo '<h3>'.$result->failureCount()." test failures</h3>\n";
1439                 printf("Time spent: %.2f secs<br/>\n", $end_time - $start_time);
1440         }
1441         else
1442         {
1443                 echo $result->failureCount()." test failures\n";
1444                 printf("Time spent: %.2f secs\n", $end_time - $start_time);
1445         }
1446
1447         if($result->failureCount() && !$DEBUG)
1448         {
1449                 $target = strpos($_SERVER['PHP_SELF'], '?') ? $_SERVER['PHP_SELF'].'&amp;DEBUG=1' : $_SERVER['PHP_SELF'].'?DEBUG=1';
1450                 $t2 = strpos($_SERVER['PHP_SELF'], '?') ? $_SERVER['PHP_SELF'].'&amp;DEBUG=2' : $_SERVER['PHP_SELF'].'?DEBUG=2';
1451                 if(isset($_SERVER['REQUEST_METHOD']))
1452                 {
1453                         echo '<p>Run testsuite with <a href="'.$target.'">DEBUG=1</a> to have more detail about tests results. Or with <a href="'.$t2.'">DEBUG=2</a> for even more.</p>'."\n";
1454                 }
1455                 else
1456                 {
1457                         echo "Run testsuite with DEBUG=1 (or 2) to have more detail about tests results\n";
1458                 }
1459         }
1460
1461         if(isset($_SERVER['REQUEST_METHOD']))
1462         {
1463 ?>
1464 <a href="#" onclick="if (document.getElementById('opts').style.display == 'block') document.getElementById('opts').style.display = 'none'; else document.getElementById('opts').style.display = 'block';">More options...</a>
1465 <div id="opts" style="display: none;">
1466 <form method="GET" style="border: 1px solid silver; margin: 5px; padding: 5px; font-family: monospace;">
1467 HTTP Server:&nbsp;&nbsp;<input name="LOCALSERVER" size="30" value="<?php echo htmlspecialchars($LOCALSERVER); ?>"/> Path: <input name="URI"  size="30" value="<?php echo htmlspecialchars($URI); ?>"/><br/>
1468 HTTPS Server: <input name="HTTPSSERVER" size="30" value="<?php echo htmlspecialchars($HTTPSSERVER); ?>"/> Path: <input name="HTTPSURI"  size="30" value="<?php echo htmlspecialchars($HTTPSURI); ?>"/><br/>
1469 Proxy Server: <input name="PROXY" size="30" value="<?php echo isset($PROXY) ? htmlspecialchars($PROXY) : ''; ?>"/> <input type="submit" value="Run Testsuite"/>
1470 </form>
1471 </div>
1472 <?php
1473                 echo $result->toHTML()."\n</body>\n</html>\n";
1474         }
1475 ?>