RemoteFilesystemTest.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <?php
  2. /*
  3. * This file is part of Composer.
  4. *
  5. * (c) Nils Adermann <naderman@naderman.de>
  6. * Jordi Boggiano <j.boggiano@seld.be>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Composer\Test\Util;
  12. use Composer\Util\RemoteFilesystem;
  13. class RemoteFilesystemTest extends \PHPUnit_Framework_TestCase
  14. {
  15. public function testGetOptionsForUrl()
  16. {
  17. $io = $this->getMock('Composer\IO\IOInterface');
  18. $io
  19. ->expects($this->once())
  20. ->method('hasAuthentication')
  21. ->will($this->returnValue(false))
  22. ;
  23. $res = $this->callGetOptionsForUrl($io, array('http://example.org', array()));
  24. $this->assertTrue(isset($res['http']['header']) && is_array($res['http']['header']), 'getOptions must return an array with headers');
  25. }
  26. public function testGetOptionsForUrlWithAuthorization()
  27. {
  28. $io = $this->getMock('Composer\IO\IOInterface');
  29. $io
  30. ->expects($this->once())
  31. ->method('hasAuthentication')
  32. ->will($this->returnValue(true))
  33. ;
  34. $io
  35. ->expects($this->once())
  36. ->method('getAuthentication')
  37. ->will($this->returnValue(array('username' => 'login', 'password' => 'password')))
  38. ;
  39. $options = $this->callGetOptionsForUrl($io, array('http://example.org', array()));
  40. $found = false;
  41. foreach ($options['http']['header'] as $header) {
  42. if (0 === strpos($header, 'Authorization: Basic')) {
  43. $found = true;
  44. }
  45. }
  46. $this->assertTrue($found, 'getOptions must have an Authorization header');
  47. }
  48. public function testGetOptionsForUrlWithStreamOptions()
  49. {
  50. $io = $this->getMock('Composer\IO\IOInterface');
  51. $io
  52. ->expects($this->once())
  53. ->method('hasAuthentication')
  54. ->will($this->returnValue(true))
  55. ;
  56. $streamOptions = array('ssl' => array(
  57. 'allow_self_signed' => true,
  58. ));
  59. $res = $this->callGetOptionsForUrl($io, array('https://example.org', array()), $streamOptions);
  60. $this->assertTrue(isset($res['ssl']) && isset($res['ssl']['allow_self_signed']) && true === $res['ssl']['allow_self_signed'], 'getOptions must return an array with a allow_self_signed set to true');
  61. }
  62. public function testGetOptionsForUrlWithCallOptionsKeepsHeader()
  63. {
  64. $io = $this->getMock('Composer\IO\IOInterface');
  65. $io
  66. ->expects($this->once())
  67. ->method('hasAuthentication')
  68. ->will($this->returnValue(true))
  69. ;
  70. $streamOptions = array('http' => array(
  71. 'header' => 'Foo: bar',
  72. ));
  73. $res = $this->callGetOptionsForUrl($io, array('https://example.org', $streamOptions));
  74. $this->assertTrue(isset($res['http']['header']), 'getOptions must return an array with a http.header key');
  75. $found = false;
  76. foreach ($res['http']['header'] as $header) {
  77. if ($header === 'Foo: bar') {
  78. $found = true;
  79. }
  80. }
  81. $this->assertTrue($found, 'getOptions must have a Foo: bar header');
  82. $this->assertGreaterThan(1, count($res['http']['header']));
  83. }
  84. public function testCallbackGetFileSize()
  85. {
  86. $fs = new RemoteFilesystem($this->getMock('Composer\IO\IOInterface'));
  87. $this->callCallbackGet($fs, STREAM_NOTIFY_FILE_SIZE_IS, 0, '', 0, 0, 20);
  88. $this->assertAttributeEquals(20, 'bytesMax', $fs);
  89. }
  90. public function testCallbackGetNotifyProgress()
  91. {
  92. $io = $this->getMock('Composer\IO\IOInterface');
  93. $io
  94. ->expects($this->once())
  95. ->method('overwriteError')
  96. ;
  97. $fs = new RemoteFilesystem($io);
  98. $this->setAttribute($fs, 'bytesMax', 20);
  99. $this->setAttribute($fs, 'progress', true);
  100. $this->callCallbackGet($fs, STREAM_NOTIFY_PROGRESS, 0, '', 0, 10, 20);
  101. $this->assertAttributeEquals(50, 'lastProgress', $fs);
  102. }
  103. public function testCallbackGetPassesThrough404()
  104. {
  105. $fs = new RemoteFilesystem($this->getMock('Composer\IO\IOInterface'));
  106. $this->assertNull($this->callCallbackGet($fs, STREAM_NOTIFY_FAILURE, 0, 'HTTP/1.1 404 Not Found', 404, 0, 0));
  107. }
  108. /**
  109. * @group slow
  110. */
  111. public function testCaptureAuthenticationParamsFromUrl()
  112. {
  113. $io = $this->getMock('Composer\IO\IOInterface');
  114. $io->expects($this->once())
  115. ->method('setAuthentication')
  116. ->with($this->equalTo('example.com'), $this->equalTo('user'), $this->equalTo('pass'));
  117. $fs = new RemoteFilesystem($io);
  118. try {
  119. $fs->getContents('example.com', 'http://user:pass@www.example.com/something');
  120. } catch (\Exception $e) {
  121. $this->assertInstanceOf('Composer\Downloader\TransportException', $e);
  122. $this->assertEquals(404, $e->getCode());
  123. }
  124. }
  125. public function testGetContents()
  126. {
  127. $fs = new RemoteFilesystem($this->getMock('Composer\IO\IOInterface'));
  128. $this->assertContains('testGetContents', $fs->getContents('http://example.org', 'file://'.__FILE__));
  129. }
  130. public function testCopy()
  131. {
  132. $fs = new RemoteFilesystem($this->getMock('Composer\IO\IOInterface'));
  133. $file = tempnam(sys_get_temp_dir(), 'c');
  134. $this->assertTrue($fs->copy('http://example.org', 'file://'.__FILE__, $file));
  135. $this->assertFileExists($file);
  136. $this->assertContains('testCopy', file_get_contents($file));
  137. unlink($file);
  138. }
  139. /**
  140. * @group TLS
  141. */
  142. public function testGetOptionsForUrlCreatesSecureTlsDefaults()
  143. {
  144. $io = $this->getMock('Composer\IO\IOInterface');
  145. $res = $this->callGetOptionsForUrl($io, array('example.org', array('ssl' => array('cafile' => '/some/path/file.crt'))), array(), 'http://www.example.org');
  146. $this->assertTrue(isset($res['ssl']['ciphers']));
  147. $this->assertRegExp("|!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK|", $res['ssl']['ciphers']);
  148. $this->assertTrue($res['ssl']['verify_peer']);
  149. $this->assertTrue($res['ssl']['SNI_enabled']);
  150. $this->assertEquals(7, $res['ssl']['verify_depth']);
  151. if (PHP_VERSION_ID < 50600) {
  152. $this->assertEquals('www.example.org', $res['ssl']['CN_match']);
  153. $this->assertEquals('www.example.org', $res['ssl']['SNI_server_name']);
  154. }
  155. $this->assertEquals('/some/path/file.crt', $res['ssl']['cafile']);
  156. if (version_compare(PHP_VERSION, '5.4.13') >= 0) {
  157. $this->assertTrue($res['ssl']['disable_compression']);
  158. } else {
  159. $this->assertFalse(isset($res['ssl']['disable_compression']));
  160. }
  161. }
  162. protected function callGetOptionsForUrl($io, array $args = array(), array $options = array(), $fileUrl = '')
  163. {
  164. $fs = new RemoteFilesystem($io, null, $options);
  165. $ref = new \ReflectionMethod($fs, 'getOptionsForUrl');
  166. $prop = new \ReflectionProperty($fs, 'fileUrl');
  167. $ref->setAccessible(true);
  168. $prop->setAccessible(true);
  169. $prop->setValue($fs, $fileUrl);
  170. return $ref->invokeArgs($fs, $args);
  171. }
  172. protected function callCallbackGet(RemoteFilesystem $fs, $notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
  173. {
  174. $ref = new \ReflectionMethod($fs, 'callbackGet');
  175. $ref->setAccessible(true);
  176. $ref->invoke($fs, $notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax);
  177. }
  178. protected function setAttribute($object, $attribute, $value)
  179. {
  180. $attr = new \ReflectionProperty($object, $attribute);
  181. $attr->setAccessible(true);
  182. $attr->setValue($object, $value);
  183. }
  184. }