PathTest.php 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862
  1. <?php
  2. namespace Path\Tests\unit;
  3. use http\Params;
  4. use Path\BuiltinProxy;
  5. use Path\Exception\FileExistsException;
  6. use Path\Exception\FileNotFoundException;
  7. use Path\Exception\IOException;
  8. use Path\Path;
  9. use PHPUnit\Framework\MockObject\MockObject;
  10. use PHPUnit\Framework\TestCase;
  11. class TestablePath extends Path {
  12. public function setBuiltin(BuiltinProxy $builtinProxy): void
  13. {
  14. $this->builtin = $builtinProxy;
  15. }
  16. public function cast(string|Path $path): Path
  17. {
  18. return parent::cast($path);
  19. }
  20. public function rrmdir(): bool {
  21. return $this->rrmdir();
  22. }
  23. public function getDirectoryIterator(): \DirectoryIterator
  24. {
  25. return parent::getDirectoryIterator();
  26. }
  27. }
  28. class PathTest extends TestCase
  29. {
  30. private BuiltinProxy | MockObject $builtin;
  31. public function setUp(): void
  32. {
  33. $this->builtin = $this->getMockBuilder(BuiltinProxy::class)->getMock();
  34. }
  35. public function getMock(string $path, string $methodName): TestablePath | MockObject
  36. {
  37. $mock = $this
  38. ->getMockBuilder(TestablePath::class)
  39. ->setConstructorArgs([$path])
  40. ->setMethodsExcept(['__toString', 'setBuiltin', $methodName])
  41. ->getMock();
  42. $mock->setBuiltin($this->builtin);
  43. return $mock;
  44. }
  45. /**
  46. * Test 'join' method.
  47. */
  48. public function testJoin(): void
  49. {
  50. // One part
  51. $this->assertEquals(
  52. '/home/user',
  53. Path::join('/home', 'user')
  54. );
  55. // Multiple parts
  56. $this->assertEquals(
  57. '/home/user/documents',
  58. Path::join('/home', 'user', 'documents')
  59. );
  60. // Absolute path passed in $parts
  61. $this->assertEquals(
  62. '/user/documents',
  63. Path::join('home', '/user', 'documents')
  64. );
  65. }
  66. public function testToString(): void
  67. {
  68. $path = new Path('/foo/bar');
  69. $this->assertEquals(
  70. '/foo/bar',
  71. $path->__toString()
  72. );
  73. }
  74. public function testPath()
  75. {
  76. $path = $this->getMock('bar', 'path');
  77. $this->assertEquals(
  78. 'bar',
  79. $path->path()
  80. );
  81. }
  82. public function testEq(): void
  83. {
  84. $path = $this->getMock('bar', 'eq');
  85. $path
  86. ->method('path')
  87. ->willReturn('bar');
  88. $path2 = $this->getMockBuilder(TestablePath::class)->disableOriginalConstructor()->getMock();
  89. $path2
  90. ->method('path')
  91. ->willReturn('bar');
  92. $path3 = $this->getMockBuilder(TestablePath::class)->disableOriginalConstructor()->getMock();
  93. $path3
  94. ->method('path')
  95. ->willReturn('/foo/bar');
  96. $path->method('cast')->willReturnMap(
  97. [
  98. [$path2, $path2],
  99. [$path3, $path3],
  100. ['bar', $path2],
  101. ['/foo/bar', $path3],
  102. ]
  103. );
  104. $this->assertTrue($path->eq($path2));
  105. $this->assertFalse($path->eq($path3));
  106. $this->assertTrue($path->eq('bar'));
  107. $this->assertFalse($path->eq('/foo/bar'));
  108. }
  109. /**
  110. * @throws IOException
  111. */
  112. public function testAbsPath(): void {
  113. $path = $this->getMock('./file.ext', 'absPath');
  114. $path->method('path')->willReturn('./file.ext');
  115. $this->builtin
  116. ->expects(self::once())
  117. ->method('realpath')
  118. ->with('./file.ext')
  119. ->willReturn('/foo/file.ext');
  120. $newPath = $this->getMockBuilder(TestablePath::class)
  121. ->disableOriginalConstructor()
  122. ->getMock();
  123. $newPath->method('path')->willReturn('/foo/file.ext');
  124. $path->method('cast')->with('/foo/file.ext')->willReturn($newPath);
  125. $this->assertEquals(
  126. '/foo/file.ext',
  127. $path->absPath()->path()
  128. );
  129. }
  130. /**
  131. * @throws IOException
  132. */
  133. public function testRealPath()
  134. {
  135. $path = $this->getMock('bar', 'realpath');
  136. $newPath = $this->getMockBuilder(TestablePath::class)->disableOriginalConstructor()->getMock();
  137. $newPath
  138. ->method('eq')
  139. ->with('/foo/bar')
  140. ->willReturn(True);
  141. $path
  142. ->expects(self::once())
  143. ->method('absPath')
  144. ->willReturn($newPath);
  145. $this->assertTrue(
  146. $path->realpath()->eq('/foo/bar')
  147. );
  148. }
  149. public function testAccessFileExist(): void
  150. {
  151. $path = $this->getMock('bar', 'access');
  152. $this->builtin
  153. ->expects(self::once())
  154. ->method('file_exists')
  155. ->with('bar')
  156. ->willReturn(true);
  157. $this->builtin
  158. ->expects(self::never())
  159. ->method('is_readable')
  160. ->with('bar')
  161. ->willReturn(true);
  162. $this->builtin
  163. ->expects(self::never())
  164. ->method('is_writable')
  165. ->with('bar')
  166. ->willReturn(true);
  167. $this->builtin
  168. ->expects(self::never())
  169. ->method('is_executable')
  170. ->with('bar')
  171. ->willReturn(true);
  172. $this->assertTrue(
  173. $path->access(Path::F_OK)
  174. );
  175. }
  176. public function testAccessIsReadable(): void
  177. {
  178. $path = $this->getMock('bar', 'access');
  179. $this->builtin
  180. ->expects(self::never())
  181. ->method('file_exists')
  182. ->with('bar')
  183. ->willReturn(true);
  184. $this->builtin
  185. ->expects(self::once())
  186. ->method('is_readable')
  187. ->with('bar')
  188. ->willReturn(true);
  189. $this->builtin
  190. ->expects(self::never())
  191. ->method('is_writable')
  192. ->with('bar')
  193. ->willReturn(true);
  194. $this->builtin
  195. ->expects(self::never())
  196. ->method('is_executable')
  197. ->with('bar')
  198. ->willReturn(true);
  199. $this->assertTrue(
  200. $path->access(Path::R_OK)
  201. );
  202. }
  203. public function testAccessIsWritable(): void
  204. {
  205. $path = $this->getMock('bar', 'access');
  206. $this->builtin
  207. ->expects(self::never())
  208. ->method('file_exists')
  209. ->with('bar')
  210. ->willReturn(true);
  211. $this->builtin
  212. ->expects(self::never())
  213. ->method('is_readable')
  214. ->with('bar')
  215. ->willReturn(true);
  216. $this->builtin
  217. ->expects(self::once())
  218. ->method('is_writable')
  219. ->with('bar')
  220. ->willReturn(true);
  221. $this->builtin
  222. ->expects(self::never())
  223. ->method('is_executable')
  224. ->with('bar')
  225. ->willReturn(true);
  226. $this->assertTrue(
  227. $path->access(Path::W_OK)
  228. );
  229. }
  230. public function testAccessIsExecutable(): void
  231. {
  232. $path = $this->getMock('bar', 'access');
  233. $this->builtin
  234. ->expects(self::never())
  235. ->method('file_exists')
  236. ->with('bar')
  237. ->willReturn(true);
  238. $this->builtin
  239. ->expects(self::never())
  240. ->method('is_readable')
  241. ->with('bar')
  242. ->willReturn(true);
  243. $this->builtin
  244. ->expects(self::never())
  245. ->method('is_writable')
  246. ->with('bar')
  247. ->willReturn(true);
  248. $this->builtin
  249. ->expects(self::once())
  250. ->method('is_executable')
  251. ->with('bar')
  252. ->willReturn(true);
  253. $this->assertTrue(
  254. $path->access(Path::X_OK)
  255. );
  256. }
  257. public function testAccessInvalidMode(): void
  258. {
  259. $path = $this->getMock('bar', 'access');
  260. $this->builtin
  261. ->expects(self::never())
  262. ->method('file_exists')
  263. ->with('bar')
  264. ->willReturn(true);
  265. $this->builtin
  266. ->expects(self::never())
  267. ->method('is_readable')
  268. ->with('bar')
  269. ->willReturn(true);
  270. $this->builtin
  271. ->expects(self::never())
  272. ->method('is_writable')
  273. ->with('bar')
  274. ->willReturn(true);
  275. $this->builtin
  276. ->expects(self::never())
  277. ->method('is_executable')
  278. ->with('bar')
  279. ->willReturn(true);
  280. $this->expectException(\RuntimeException::class);
  281. $path->access(-1);
  282. }
  283. /**
  284. * @throws IOException
  285. * @throws FileNotFoundException
  286. */
  287. public function testATime(): void
  288. {
  289. $path = $this->getMock('bar', 'atime');
  290. $path->method('exists')->willReturn(True);
  291. $ts = 1000;
  292. $this->builtin
  293. ->expects(self::once())
  294. ->method('fileatime')
  295. ->with('bar')
  296. ->willReturn($ts);
  297. $this->assertEquals(
  298. $ts,
  299. $path->atime()
  300. );
  301. }
  302. /**
  303. * @throws IOException
  304. * @throws FileNotFoundException
  305. */
  306. public function testATimeFileDoesNotExist(): void
  307. {
  308. $path = $this->getMock('bar', 'atime');
  309. $path->method('exists')->willReturn(False);
  310. $this->builtin
  311. ->expects(self::never())
  312. ->method('fileatime');
  313. $this->expectException(FileNotFoundException::class);
  314. $path->atime();
  315. }
  316. /**
  317. * @throws FileNotFoundException
  318. */
  319. public function testATimeError(): void
  320. {
  321. $path = $this->getMock('bar', 'atime');
  322. $path->method('exists')->willReturn(True);
  323. $this->builtin
  324. ->expects(self::once())
  325. ->method('fileatime')
  326. ->with('bar')
  327. ->willReturn(false);
  328. $this->expectException(IOException::class);
  329. $path->atime();
  330. }
  331. public function testCTime(): void
  332. {
  333. $path = $this->getMock('bar', 'ctime');
  334. $this->builtin
  335. ->expects(self::once())
  336. ->method('filectime')
  337. ->with('bar')
  338. ->willReturn(1000);
  339. $date = '2000-01-01';
  340. $this->builtin
  341. ->expects(self::once())
  342. ->method('date')
  343. ->with('Y-m-d H:i:s', 1000)
  344. ->willReturn($date);
  345. $this->assertEquals(
  346. $date,
  347. $path->ctime()
  348. );
  349. }
  350. /**
  351. * @throws IOException
  352. * @throws FileNotFoundException
  353. */
  354. public function testCTimeFileDoesNotExist(): void
  355. {
  356. $path = $this->getMock('bar', 'ctime');
  357. $path->method('exists')->willReturn(False);
  358. $this->builtin
  359. ->expects(self::never())
  360. ->method('filectime');
  361. $this->expectException(FileNotFoundException::class);
  362. $path->ctime();
  363. }
  364. /**
  365. * @throws FileNotFoundException
  366. */
  367. public function testCTimeError(): void
  368. {
  369. $path = $this->getMock('bar', 'ctime');
  370. $path->method('exists')->willReturn(True);
  371. $this->builtin
  372. ->expects(self::once())
  373. ->method('filectime')
  374. ->with('bar')
  375. ->willReturn(false);
  376. $this->expectException(IOException::class);
  377. $path->ctime();
  378. }
  379. public function testMTime(): void
  380. {
  381. $path = $this->getMock('bar', 'mtime');
  382. $this->builtin
  383. ->expects(self::once())
  384. ->method('filemtime')
  385. ->with('bar')
  386. ->willReturn(1000);
  387. $date = '2000-01-01';
  388. $this->builtin
  389. ->expects(self::once())
  390. ->method('date')
  391. ->with('Y-m-d H:i:s', 1000)
  392. ->willReturn($date);
  393. $this->assertEquals(
  394. $date,
  395. $path->mtime()
  396. );
  397. }
  398. /**
  399. * @throws IOException
  400. * @throws FileNotFoundException
  401. */
  402. public function testMTimeFileDoesNotExist(): void
  403. {
  404. $path = $this->getMock('bar', 'mtime');
  405. $path->method('exists')->willReturn(False);
  406. $this->builtin
  407. ->expects(self::never())
  408. ->method('filemtime');
  409. $this->expectException(FileNotFoundException::class);
  410. $path->mtime();
  411. }
  412. /**
  413. * @throws FileNotFoundException
  414. */
  415. public function testMTimeError(): void
  416. {
  417. $path = $this->getMock('bar', 'mtime');
  418. $path->method('exists')->willReturn(True);
  419. $this->builtin
  420. ->expects(self::once())
  421. ->method('filemtime')
  422. ->with('bar')
  423. ->willReturn(false);
  424. $this->expectException(IOException::class);
  425. $path->mtime();
  426. }
  427. public function testIsFile(): void
  428. {
  429. $path = $this->getMock('bar', 'isFile');
  430. $this->builtin
  431. ->expects(self::once())
  432. ->method('is_file')
  433. ->with('bar')
  434. ->willReturn(true);
  435. $this->assertTrue(
  436. $path->isFile()
  437. );
  438. }
  439. public function testIsDir(): void
  440. {
  441. $path = $this->getMock('bar', 'isDir');
  442. $this->builtin
  443. ->expects(self::once())
  444. ->method('is_dir')
  445. ->with('bar')
  446. ->willReturn(true);
  447. $this->assertTrue(
  448. $path->isDir()
  449. );
  450. }
  451. public function testExt(): void
  452. {
  453. $path = $this->getMock('bar.ext', 'ext');
  454. $this->builtin
  455. ->expects(self::once())
  456. ->method('pathinfo')
  457. ->with('bar.ext', PATHINFO_EXTENSION)
  458. ->willReturn('ext');
  459. $this->assertEquals(
  460. 'ext',
  461. $path->ext()
  462. );
  463. }
  464. public function testExtNoExt(): void
  465. {
  466. $path = $this->getMock('bar', 'ext');
  467. $this->builtin
  468. ->expects(self::once())
  469. ->method('pathinfo')
  470. ->with('bar', PATHINFO_EXTENSION)
  471. ->willReturn('');
  472. $this->assertEquals(
  473. '',
  474. $path->ext()
  475. );
  476. }
  477. public function testBaseName(): void
  478. {
  479. $path = $this->getMock('bar.ext', 'basename');
  480. $this->builtin
  481. ->expects(self::once())
  482. ->method('pathinfo')
  483. ->with('bar.ext', PATHINFO_BASENAME)
  484. ->willReturn('bar.ext');
  485. $this->assertEquals(
  486. 'bar.ext',
  487. $path->basename()
  488. );
  489. }
  490. /**
  491. * @throws IOException
  492. * @throws FileNotFoundException
  493. */
  494. public function testCD(): void
  495. {
  496. $path = $this->getMock('bar', 'cd');
  497. $path->method('exists')->willReturn(True);
  498. $this->builtin
  499. ->expects(self::once())
  500. ->method('chdir')
  501. ->with('bar')
  502. ->willReturn(True);
  503. $path->cd();
  504. }
  505. /**
  506. * @throws IOException
  507. * @throws FileNotFoundException
  508. */
  509. public function testCDDirDoesNotExist(): void
  510. {
  511. $path = $this->getMock('bar', 'cd');
  512. $path->method('exists')->willReturn(False);
  513. $this->builtin
  514. ->expects(self::never())
  515. ->method('chdir');
  516. $this->expectException(FileNotFoundException::class);
  517. $path->cd();
  518. }
  519. /**
  520. * @throws IOException
  521. * @throws FileNotFoundException
  522. */
  523. public function testCDWithError(): void
  524. {
  525. $path = $this->getMock('bar', 'cd');
  526. $path->method('exists')->willReturn(True);
  527. $this->builtin
  528. ->expects(self::once())
  529. ->method('chdir')
  530. ->with('bar')
  531. ->willReturn(False);
  532. $this->expectException(IOException::class);
  533. $path->cd();
  534. }
  535. public function testChDir(): void
  536. {
  537. $path = $this->getMock('bar', 'chdir');
  538. $path
  539. ->expects(self::once())
  540. ->method('cd')
  541. ->with('foo')
  542. ->willReturn(true);
  543. $this->assertTrue(
  544. $path->cd('foo')
  545. );
  546. }
  547. public function testName(): void
  548. {
  549. $path = $this->getMock('bar.ext', 'name');
  550. $this->builtin
  551. ->expects(self::once())
  552. ->method('pathinfo')
  553. ->with('bar.ext', PATHINFO_FILENAME)
  554. ->willReturn('bar');
  555. $this->assertEquals(
  556. 'bar',
  557. $path->name()
  558. );
  559. }
  560. /**
  561. * @throws IOException
  562. * @throws FileExistsException
  563. */
  564. public function testMkDir(): void
  565. {
  566. $path = $this->getMock('foo', 'mkdir');
  567. $path->method('isDir')->willReturn(False);
  568. $path->method('isFile')->willReturn(False);
  569. $this->builtin
  570. ->expects(self::once())
  571. ->method('mkdir')
  572. ->with('foo', 0777, false)
  573. ->willReturn(true);
  574. $path->mkdir();
  575. }
  576. /**
  577. * @throws IOException
  578. */
  579. public function testMkDirAlreadyExist(): void
  580. {
  581. $path = $this->getMock('foo', 'mkdir');
  582. $path->method('isDir')->willReturn(True);
  583. $this->expectException(FileExistsException::class);
  584. $path->mkdir();
  585. }
  586. /**
  587. * @throws IOException
  588. * @throws FileExistsException
  589. */
  590. public function testMkDirAlreadyExistButRecursive(): void
  591. {
  592. $path = $this->getMock('foo', 'mkdir');
  593. $path->method('isDir')->willReturn(True);
  594. $this->builtin
  595. ->expects(self::never())
  596. ->method('mkdir');
  597. $path->mkdir(0777, true);
  598. }
  599. /**
  600. * @throws IOException
  601. * @throws FileExistsException
  602. */
  603. public function testMkDirFileExists(): void
  604. {
  605. $path = $this->getMock('foo', 'mkdir');
  606. $path->method('isDir')->willReturn(False);
  607. $path->method('isFile')->willReturn(True);
  608. $this->expectException(FileExistsException::class);
  609. $path->mkdir();
  610. }
  611. /**
  612. * @throws IOException
  613. * @throws FileExistsException
  614. */
  615. public function testMkDirFileExistsButRecursive(): void
  616. {
  617. $path = $this->getMock('foo', 'mkdir');
  618. $path->method('isDir')->willReturn(False);
  619. $path->method('isFile')->willReturn(True);
  620. $this->expectException(FileExistsException::class);
  621. $path->mkdir(0777, true);
  622. }
  623. /**
  624. * @throws IOException
  625. * @throws FileExistsException
  626. */
  627. public function testMkDirIoError(): void
  628. {
  629. $path = $this->getMock('foo', 'mkdir');
  630. $path->method('isDir')->willReturn(False);
  631. $path->method('isFile')->willReturn(False);
  632. $this->builtin
  633. ->expects(self::once())
  634. ->method('mkdir')
  635. ->with('foo', 0777, false)
  636. ->willReturn(false);
  637. $this->expectException(IOException::class);
  638. $path->mkdir();
  639. }
  640. /**
  641. * @throws IOException
  642. * @throws FileNotFoundException
  643. */
  644. public function testDeleteIsFile(): void
  645. {
  646. $path = $this->getMock('foo', 'delete');
  647. $path->method('isFile')->willReturn(True);
  648. $path->method('isDir')->willReturn(False);
  649. $this->builtin
  650. ->expects(self::once())
  651. ->method('unlink')
  652. ->with('foo')
  653. ->willReturn(true);
  654. $path->delete();
  655. }
  656. /**
  657. * @throws IOException
  658. * @throws FileNotFoundException
  659. */
  660. public function testDeleteIsFileWithError(): void
  661. {
  662. $path = $this->getMock('foo', 'delete');
  663. $path->method('isFile')->willReturn(True);
  664. $path->method('isDir')->willReturn(False);
  665. $this->builtin
  666. ->expects(self::once())
  667. ->method('unlink')
  668. ->with('foo')
  669. ->willReturn(false);
  670. $this->expectException(IOException::class);
  671. $path->delete();
  672. }
  673. /**
  674. * @throws IOException
  675. * @throws FileNotFoundException
  676. */
  677. public function testDeleteIsDir(): void
  678. {
  679. $path = $this->getMock('foo', 'delete');
  680. $path->method('isFile')->willReturn(False);
  681. $path->method('isDir')->willReturn(True);
  682. $this->builtin
  683. ->expects(self::once())
  684. ->method('rmdir')
  685. ->with('foo')
  686. ->willReturn(true);
  687. $path->delete();
  688. }
  689. /**
  690. * @throws IOException
  691. * @throws FileNotFoundException
  692. */
  693. public function testDeleteIsDirWithError(): void
  694. {
  695. $path = $this->getMock('foo', 'delete');
  696. $path->method('isFile')->willReturn(False);
  697. $path->method('isDir')->willReturn(True);
  698. $this->builtin
  699. ->expects(self::once())
  700. ->method('rmdir')
  701. ->with('foo')
  702. ->willReturn(false);
  703. $this->expectException(IOException::class);
  704. $path->delete();
  705. }
  706. /**
  707. * @throws IOException
  708. * @throws FileNotFoundException
  709. */
  710. public function testDeleteNonExistentFile(): void
  711. {
  712. $path = $this->getMock('foo', 'delete');
  713. $path->method('isFile')->willReturn(False);
  714. $path->method('isDir')->willReturn(False);
  715. $this->builtin
  716. ->expects(self::never())
  717. ->method('unlink');
  718. $this->builtin
  719. ->expects(self::never())
  720. ->method('rmdir');
  721. $this->expectException(FileNotFoundException::class);
  722. $path->delete();
  723. }
  724. /**
  725. * @throws IOException
  726. * @throws FileNotFoundException
  727. * @throws FileExistsException
  728. */
  729. public function testCopy()
  730. {
  731. $path = $this->getMock('foo.ext', 'copy');
  732. $path->method('isFile')->willReturn(True);
  733. $destination = "/bar/foo2.ext";
  734. $this->builtin
  735. ->expects(self::once())
  736. ->method('is_dir')
  737. ->with($destination)
  738. ->willReturn(False);
  739. $this->builtin
  740. ->expects(self::once())
  741. ->method('file_exists')
  742. ->with($destination)
  743. ->willReturn(False);
  744. $this->builtin
  745. ->expects(self::once())
  746. ->method('copy')
  747. ->with('foo.ext', $destination)
  748. ->willReturn(True);
  749. $newPath = $this->getMockBuilder(TestablePath::class)->disableOriginalConstructor()->getMock();
  750. $newPath->method('eq')->with($destination)->willReturn(True);
  751. $path->method('cast')->with($destination)->willReturn($newPath);
  752. $result = $path->copy($destination);
  753. $this->assertTrue(
  754. $result->eq($destination)
  755. );
  756. }
  757. /**
  758. * @throws IOException
  759. * @throws FileNotFoundException
  760. * @throws FileExistsException
  761. */
  762. public function testCopyFileDoesNotExist()
  763. {
  764. $path = $this->getMock('foo.ext', 'copy');
  765. $path->method('isFile')->willReturn(False);
  766. $destination = "/bar/foo2.ext";
  767. $this->builtin
  768. ->expects(self::never())
  769. ->method('is_dir');
  770. $this->builtin
  771. ->expects(self::never())
  772. ->method('file_exists');
  773. $this->builtin
  774. ->expects(self::never())
  775. ->method('copy');
  776. $this->expectException(FileNotFoundException::class);
  777. $path->copy($destination);
  778. }
  779. /**
  780. * @throws IOException
  781. * @throws FileNotFoundException
  782. * @throws FileExistsException
  783. */
  784. public function testCopyDestIsDir()
  785. {
  786. $path = $this->getMock('foo.ext', 'copy');
  787. $path->method('isFile')->willReturn(True);
  788. $path->method('basename')->willReturn('foo.ext');
  789. $destination = "/bar";
  790. $this->builtin
  791. ->expects(self::once())
  792. ->method('is_dir')
  793. ->with($destination)
  794. ->willReturn(True);
  795. $newDest = $destination . "/foo.ext";
  796. $this->builtin
  797. ->expects(self::once())
  798. ->method('file_exists')
  799. ->with($newDest)
  800. ->willReturn(False);
  801. $this->builtin
  802. ->expects(self::once())
  803. ->method('copy')
  804. ->with('foo.ext', $newDest)
  805. ->willReturn(True);
  806. $newPath = $this->getMockBuilder(TestablePath::class)->disableOriginalConstructor()->getMock();
  807. $newPath->method('eq')->with($newDest)->willReturn(True);
  808. $path->method('cast')->with($newDest)->willReturn($newPath);
  809. $result = $path->copy($destination);
  810. $this->assertTrue(
  811. $result->eq($newDest)
  812. );
  813. }
  814. /**
  815. * @throws IOException
  816. * @throws FileNotFoundException
  817. * @throws FileExistsException
  818. */
  819. public function testCopyFileAlreadyExists()
  820. {
  821. $path = $this->getMock('foo.ext', 'copy');
  822. $path->method('isFile')->willReturn(True);
  823. $destination = "/bar/foo2.ext";
  824. $this->builtin
  825. ->expects(self::once())
  826. ->method('is_dir')
  827. ->with($destination)
  828. ->willReturn(False);
  829. $this->builtin
  830. ->expects(self::once())
  831. ->method('file_exists')
  832. ->with($destination)
  833. ->willReturn(True);
  834. $this->builtin
  835. ->expects(self::never())
  836. ->method('copy');
  837. $this->expectException(FileExistsException::class);
  838. $path->copy($destination);
  839. }
  840. /**
  841. * @throws IOException
  842. * @throws FileNotFoundException
  843. * @throws FileExistsException
  844. */
  845. public function testCopyFileDestIsDirButFileAlreadyExists()
  846. {
  847. $path = $this->getMock('foo.ext', 'copy');
  848. $path->method('isFile')->willReturn(True);
  849. $path->method('basename')->willReturn('foo.ext');
  850. $destination = "/bar";
  851. $this->builtin
  852. ->expects(self::once())
  853. ->method('is_dir')
  854. ->with($destination)
  855. ->willReturn(True);
  856. $newDest = $destination . "/foo.ext";
  857. $this->builtin
  858. ->expects(self::once())
  859. ->method('file_exists')
  860. ->with($newDest)
  861. ->willReturn(True);
  862. $this->builtin
  863. ->expects(self::never())
  864. ->method('copy');
  865. $this->expectException(FileExistsException::class);
  866. $path->copy($destination);
  867. }
  868. /**
  869. * @throws IOException
  870. * @throws FileNotFoundException
  871. * @throws FileExistsException
  872. */
  873. public function testCopyFileWithError()
  874. {
  875. $path = $this->getMock('foo.ext', 'copy');
  876. $path->method('isFile')->willReturn(True);
  877. $destination = "/bar/foo2.ext";
  878. $this->builtin
  879. ->expects(self::once())
  880. ->method('is_dir')
  881. ->with($destination)
  882. ->willReturn(False);
  883. $this->builtin
  884. ->expects(self::once())
  885. ->method('file_exists')
  886. ->with($destination)
  887. ->willReturn(False);
  888. $this->builtin
  889. ->expects(self::once())
  890. ->method('copy')
  891. ->with('foo.ext', $destination)
  892. ->willReturn(False);
  893. $this->expectException(IOException::class);
  894. $path->copy($destination);
  895. }
  896. // public function testCopyTree(): void {
  897. // TODO: implement
  898. // }
  899. /**
  900. * @throws IOException
  901. * @throws FileExistsException
  902. */
  903. public function testMove()
  904. {
  905. $path = $this->getMock('foo.ext', 'move');
  906. $destination = "/bar/foo2.ext";
  907. $this->builtin
  908. ->expects(self::once())
  909. ->method('is_dir')
  910. ->with($destination)
  911. ->willReturn(False);
  912. $this->builtin
  913. ->expects(self::once())
  914. ->method('file_exists')
  915. ->with($destination)
  916. ->willReturn(False);
  917. $this->builtin
  918. ->expects(self::once())
  919. ->method('rename')
  920. ->with('foo.ext', $destination)
  921. ->willReturn(True);
  922. $destinationPath = $this->getMockBuilder(TestablePath::class)->disableOriginalConstructor()->getMock();
  923. $destinationPath->method('eq')->with($destination)->willReturn(True);
  924. $path->method('cast')->with($destination)->willReturn($destinationPath);
  925. $result = $path->move($destination);
  926. $this->assertTrue(
  927. $result->eq($destination)
  928. );
  929. }
  930. /**
  931. * @throws IOException
  932. * @throws FileExistsException
  933. */
  934. public function testMoveWithPath()
  935. {
  936. $path = $this->getMock('foo.ext', 'move');
  937. $destination = new Path("/bar/foo2.ext");
  938. $this->builtin
  939. ->expects(self::once())
  940. ->method('is_dir')
  941. ->with($destination)
  942. ->willReturn(False);
  943. $this->builtin
  944. ->expects(self::once())
  945. ->method('file_exists')
  946. ->with($destination)
  947. ->willReturn(False);
  948. $this->builtin
  949. ->expects(self::once())
  950. ->method('rename')
  951. ->with('foo.ext', $destination)
  952. ->willReturn(True);
  953. $destinationPath = $this->getMockBuilder(TestablePath::class)->disableOriginalConstructor()->getMock();
  954. $destinationPath->method('eq')->with($destination)->willReturn(True);
  955. $path->method('cast')->with($destination)->willReturn($destinationPath);
  956. $result = $path->move($destination);
  957. $this->assertTrue(
  958. $result->eq($destination)
  959. );
  960. }
  961. /**
  962. * @throws IOException
  963. * @throws FileExistsException
  964. */
  965. public function testMoveDestIsDir()
  966. {
  967. $path = $this->getMock('foo.ext', 'move');
  968. $path->method('basename')->willReturn('foo.ext');
  969. $destination = "/bar";
  970. $this->builtin
  971. ->expects(self::once())
  972. ->method('is_dir')
  973. ->with($destination)
  974. ->willReturn(True);
  975. $newDestination = $destination . "/foo.ext";
  976. $this->builtin
  977. ->expects(self::once())
  978. ->method('file_exists')
  979. ->with($newDestination)
  980. ->willReturn(False);
  981. $this->builtin
  982. ->expects(self::once())
  983. ->method('rename')
  984. ->with('foo.ext', $newDestination)
  985. ->willReturn(True);
  986. $destinationPath = $this->getMockBuilder(TestablePath::class)->disableOriginalConstructor()->getMock();
  987. $destinationPath->method('eq')->with($newDestination)->willReturn(True);
  988. $path->method('cast')->with($newDestination)->willReturn($destinationPath);
  989. $result = $path->move($destination);
  990. $this->assertTrue(
  991. $result->eq($newDestination)
  992. );
  993. }
  994. /**
  995. * @throws IOException
  996. * @throws FileExistsException
  997. */
  998. public function testMoveFileExist()
  999. {
  1000. $path = $this->getMock('foo.ext', 'move');
  1001. $path->method('basename')->willReturn('foo.ext');
  1002. $destination = "/bar/foo2.ext";
  1003. $this->builtin
  1004. ->expects(self::once())
  1005. ->method('is_dir')
  1006. ->with($destination)
  1007. ->willReturn(False);
  1008. $this->builtin
  1009. ->expects(self::once())
  1010. ->method('file_exists')
  1011. ->with($destination)
  1012. ->willReturn(True);
  1013. $this->builtin
  1014. ->expects(self::never())
  1015. ->method('rename');
  1016. $this->expectException(FileExistsException::class);
  1017. $path->move($destination);
  1018. }
  1019. /**
  1020. * @throws IOException
  1021. * @throws FileExistsException
  1022. */
  1023. public function testMoveWithError()
  1024. {
  1025. $path = $this->getMock('foo.ext', 'move');
  1026. $path->method('basename')->willReturn('foo.ext');
  1027. $destination = "/bar/foo2.ext";
  1028. $this->builtin
  1029. ->expects(self::once())
  1030. ->method('is_dir')
  1031. ->with($destination)
  1032. ->willReturn(False);
  1033. $this->builtin
  1034. ->expects(self::once())
  1035. ->method('file_exists')
  1036. ->with($destination)
  1037. ->willReturn(False);
  1038. $this->builtin
  1039. ->expects(self::once())
  1040. ->method('rename')
  1041. ->with('foo.ext', $destination)
  1042. ->willReturn(False);
  1043. $this->expectException(IOException::class);
  1044. $path->move($destination);
  1045. }
  1046. /**
  1047. * @throws IOException
  1048. */
  1049. public function testTouchWithNoTimestamps()
  1050. {
  1051. $path = $this->getMock('foo.ext', 'touch');
  1052. $this->builtin
  1053. ->expects(self::once())
  1054. ->method('touch')
  1055. ->with('foo.ext', null, null)
  1056. ->willReturn(True);
  1057. $path->touch();
  1058. }
  1059. /**
  1060. * @throws IOException
  1061. */
  1062. public function testTouchWithTimestamps()
  1063. {
  1064. $path = $this->getMock('foo.ext', 'touch');
  1065. $this->builtin
  1066. ->expects(self::once())
  1067. ->method('touch')
  1068. ->with('foo.ext', 123, 456)
  1069. ->willReturn(True);
  1070. $path->touch(123, 456);
  1071. }
  1072. /**
  1073. * @throws IOException
  1074. */
  1075. public function testTouchWithDatetimes()
  1076. {
  1077. $path = $this->getMock('foo.ext', 'touch');
  1078. $datetime1 = $this->getMockBuilder(\DateTime::class)->getMock();
  1079. $datetime1->method('getTimestamp')->willReturn(123);
  1080. $datetime2 = $this->getMockBuilder(\DateTime::class)->getMock();
  1081. $datetime2->method('getTimestamp')->willReturn(456);
  1082. $this->builtin
  1083. ->expects(self::once())
  1084. ->method('touch')
  1085. ->with('foo.ext', 123, 456)
  1086. ->willReturn(True);
  1087. $path->touch($datetime1, $datetime2);
  1088. }
  1089. /**
  1090. * @throws IOException
  1091. */
  1092. public function testTouchWithError()
  1093. {
  1094. $path = $this->getMock('foo.ext', 'touch');
  1095. $this->builtin
  1096. ->expects(self::once())
  1097. ->method('touch')
  1098. ->with('foo.ext')
  1099. ->willReturn(False);
  1100. $this->expectException(IOException::class);
  1101. $path->touch();
  1102. }
  1103. /**
  1104. * @throws IOException
  1105. * @throws FileNotFoundException
  1106. */
  1107. public function testSize()
  1108. {
  1109. $path = $this->getMock('foo.ext', 'size');
  1110. $path->method('isFile')->willReturn(True);
  1111. $this->builtin
  1112. ->expects(self::once())
  1113. ->method('filesize')
  1114. ->with('foo.ext')
  1115. ->willReturn(123456);
  1116. $this->assertEquals(
  1117. 123456,
  1118. $path->size()
  1119. );
  1120. }
  1121. /**
  1122. * @throws IOException
  1123. * @throws FileNotFoundException
  1124. */
  1125. public function testSizeFileNotExist()
  1126. {
  1127. $path = $this->getMock('foo.ext', 'size');
  1128. $path->method('isFile')->willReturn(False);
  1129. $this->builtin
  1130. ->expects(self::never())
  1131. ->method('filesize');
  1132. $this->expectException(FileNotFoundException::class);
  1133. $path->size();
  1134. }
  1135. /**
  1136. * @throws IOException
  1137. * @throws FileNotFoundException
  1138. */
  1139. public function testSizeFileWithError()
  1140. {
  1141. $path = $this->getMock('foo.ext', 'size');
  1142. $path->method('isFile')->willReturn(True);
  1143. $this->builtin
  1144. ->expects(self::once())
  1145. ->method('filesize')
  1146. ->with('foo.ext')
  1147. ->willReturn(False);
  1148. $this->expectException(IOException::class);
  1149. $path->size();
  1150. }
  1151. public function testParent(): void
  1152. {
  1153. $path = $this->getMock('/foo/foo.ext', 'parent');
  1154. $this->builtin
  1155. ->expects(self::once())
  1156. ->method('dirname')
  1157. ->with('/foo/foo.ext')
  1158. ->willReturn('/foo');
  1159. $newPath = $this->getMockBuilder(TestablePath::class)->disableOriginalConstructor()->getMock();
  1160. $path->method('cast')->with('/foo')->willReturn($newPath);
  1161. $newPath->method('eq')->with('/foo')->willReturn(True);
  1162. $this->assertTrue(
  1163. $path->parent()->eq('/foo')
  1164. );
  1165. }
  1166. public function testDirName(): void
  1167. {
  1168. $path = $this->getMock('/foo/foo.ext', 'dirname');
  1169. $newPath = $this->getMockBuilder(TestablePath::class)->disableOriginalConstructor()->getMock();
  1170. $newPath->method('eq')->with('/foo')->willReturn(True);
  1171. $path
  1172. ->expects(self::once())
  1173. ->method('parent')
  1174. ->willReturn($newPath);
  1175. $this->assertTrue(
  1176. $path->dirname()->eq('/foo')
  1177. );
  1178. }
  1179. /**
  1180. * @throws FileNotFoundException
  1181. */
  1182. public function testDirs()
  1183. {
  1184. $path = $this->getMock('/foo', 'dirs');
  1185. $this->builtin
  1186. ->method('is_dir')
  1187. ->willReturnMap(
  1188. [
  1189. ['/foo', True],
  1190. ['/foo/file.ext', False],
  1191. ['/foo/dir1', True],
  1192. ['/foo/dir2', True],
  1193. ]
  1194. );
  1195. $results = [
  1196. '..',
  1197. '.',
  1198. 'file.ext',
  1199. 'dir1',
  1200. 'dir2'
  1201. ];
  1202. $this->builtin
  1203. ->expects(self::once())
  1204. ->method('scandir')
  1205. ->with('/foo')
  1206. ->willReturn($results);
  1207. $this->assertEquals(
  1208. ['dir1', 'dir2'],
  1209. $path->dirs()
  1210. );
  1211. }
  1212. /**
  1213. * @throws FileNotFoundException
  1214. */
  1215. public function testDirsIsNotDir()
  1216. {
  1217. $path = $this->getMock('/foo', 'dirs');
  1218. $this->builtin
  1219. ->method('is_dir')
  1220. ->with('/foo')
  1221. ->willReturn(False);
  1222. $this->expectException(FileNotFoundException::class);
  1223. $path->dirs();
  1224. }
  1225. /**
  1226. * @throws FileNotFoundException
  1227. */
  1228. public function testFiles()
  1229. {
  1230. $path = $this->getMock('/foo', 'files');
  1231. $this->builtin
  1232. ->method('is_dir')
  1233. ->with('/foo')
  1234. ->willReturn(True);
  1235. $this->builtin
  1236. ->method('is_file')
  1237. ->willReturnMap(
  1238. [
  1239. ['/foo/file1.ext', True],
  1240. ['/foo/file2.ext', True],
  1241. ['/foo/dir1', False],
  1242. ]
  1243. );
  1244. $results = [
  1245. '..',
  1246. '.',
  1247. 'file1.ext',
  1248. 'file2.ext',
  1249. 'dir1'
  1250. ];
  1251. $this->builtin
  1252. ->expects(self::once())
  1253. ->method('scandir')
  1254. ->with('/foo')
  1255. ->willReturn($results);
  1256. $this->assertEquals(
  1257. ['file1.ext', 'file2.ext'],
  1258. $path->files()
  1259. );
  1260. }
  1261. /**
  1262. * @throws FileNotFoundException
  1263. */
  1264. public function testFilesIsNotDir()
  1265. {
  1266. $path = $this->getMock('/foo', 'files');
  1267. $this->builtin
  1268. ->method('is_dir')
  1269. ->with('/foo')
  1270. ->willReturn(False);
  1271. $this->expectException(FileNotFoundException::class);
  1272. $path->files();
  1273. }
  1274. // public function testFnMatch(): void
  1275. // {
  1276. // //TODO: implements
  1277. // }
  1278. /**
  1279. * @throws IOException
  1280. * @throws FileNotFoundException
  1281. */
  1282. public function testGetContent(): void
  1283. {
  1284. $path = $this->getMock('/foo/file.ext', 'getContent');
  1285. $this->builtin
  1286. ->method('is_file')
  1287. ->with('/foo/file.ext')
  1288. ->willReturn(True);
  1289. $this->builtin
  1290. ->method('file_get_contents')
  1291. ->with('/foo/file.ext')
  1292. ->willReturn('azerty');
  1293. $this->assertEquals(
  1294. 'azerty',
  1295. $path->getContent()
  1296. );
  1297. }
  1298. /**
  1299. * @throws IOException
  1300. * @throws FileNotFoundException
  1301. */
  1302. public function testGetContentFileDoesNotExist(): void
  1303. {
  1304. $path = $this->getMock('/foo/file.ext', 'getContent');
  1305. $this->builtin
  1306. ->method('is_file')
  1307. ->with('/foo/file.ext')
  1308. ->willReturn(False);
  1309. $this->builtin
  1310. ->expects(self::never())
  1311. ->method('file_get_contents');
  1312. $this->expectException(FileNotFoundException::class);
  1313. $path->getContent();
  1314. }
  1315. /**
  1316. * @throws IOException
  1317. * @throws FileNotFoundException
  1318. */
  1319. public function testGetContentErrorWhileReading(): void
  1320. {
  1321. $path = $this->getMock('/foo/file.ext', 'getContent');
  1322. $this->builtin
  1323. ->method('is_file')
  1324. ->with('/foo/file.ext')
  1325. ->willReturn(True);
  1326. $this->builtin
  1327. ->method('file_get_contents')
  1328. ->with('/foo/file.ext')
  1329. ->willReturn(False);
  1330. $this->expectException(IOException::class);
  1331. $path->getContent();
  1332. }
  1333. /**
  1334. * @throws IOException
  1335. * @throws FileNotFoundException
  1336. */
  1337. public function testPutContent(): void
  1338. {
  1339. $path = $this->getMock('/foo/file.ext', 'putContent');
  1340. $this->builtin
  1341. ->method('is_file')
  1342. ->with('/foo/file.ext')
  1343. ->willReturn(True);
  1344. $this->builtin
  1345. ->expects(self::once())
  1346. ->method('file_put_contents')
  1347. ->with('/foo/file.ext', 'azerty')
  1348. ->willReturn(6);
  1349. $this->assertEquals(
  1350. 6,
  1351. $path->putContent('azerty')
  1352. );
  1353. }
  1354. /**
  1355. * @throws IOException
  1356. * @throws FileNotFoundException
  1357. */
  1358. public function testPutContentAndAppend(): void
  1359. {
  1360. $path = $this->getMock('/foo/file.ext', 'putContent');
  1361. $this->builtin
  1362. ->method('is_file')
  1363. ->with('/foo/file.ext')
  1364. ->willReturn(True);
  1365. $this->builtin
  1366. ->expects(self::once())
  1367. ->method('file_put_contents')
  1368. ->with('/foo/file.ext', 'azerty', FILE_APPEND)
  1369. ->willReturn(6);
  1370. $this->assertEquals(
  1371. 6,
  1372. $path->putContent('azerty', True)
  1373. );
  1374. }
  1375. /**
  1376. * @throws IOException
  1377. * @throws FileNotFoundException
  1378. */
  1379. public function testPutContentFileDoesNotExist(): void
  1380. {
  1381. $path = $this->getMock('/foo/file.ext', 'putContent');
  1382. $this->builtin
  1383. ->method('is_file')
  1384. ->with('/foo/file.ext')
  1385. ->willReturn(False);
  1386. $this->builtin
  1387. ->expects(self::never())
  1388. ->method('file_put_contents');
  1389. $this->expectException(FileNotFoundException::class);
  1390. $path->putContent('azerty');
  1391. }
  1392. /**
  1393. * @throws IOException
  1394. * @throws FileNotFoundException
  1395. */
  1396. public function testPutContentErrorWhileWriting(): void
  1397. {
  1398. $path = $this->getMock('/foo/file.ext', 'putContent');
  1399. $this->builtin
  1400. ->method('is_file')
  1401. ->with('/foo/file.ext')
  1402. ->willReturn(True);
  1403. $this->builtin
  1404. ->method('file_put_contents')
  1405. ->with('/foo/file.ext')
  1406. ->willReturn(False);
  1407. $this->expectException(IOException::class);
  1408. $path->putContent('azerty');
  1409. }
  1410. /**
  1411. * @throws IOException
  1412. * @throws FileNotFoundException
  1413. */
  1414. public function testPutLines(): void
  1415. {
  1416. $path = $this->getMock('/foo/file.ext', 'putLines');
  1417. $lines = [
  1418. 'once upon a time',
  1419. 'a man and a spoon',
  1420. 'had a great time drinking coffee'
  1421. ];
  1422. $path
  1423. ->expects(self::once())
  1424. ->method('putContent')
  1425. ->with(implode(PHP_EOL, $lines))
  1426. ->willReturn(123);
  1427. $this->assertEquals(
  1428. 123,
  1429. $path->putLines($lines)
  1430. );
  1431. }
  1432. /**
  1433. * @throws IOException
  1434. * @throws FileNotFoundException
  1435. */
  1436. public function testGetPermissions(): void
  1437. {
  1438. $path = $this->getMock('/foo/file.ext', 'getPermissions');
  1439. $path->method('isFile')->willReturn(True);
  1440. $this->builtin
  1441. ->method('fileperms')
  1442. ->with('/foo/file.ext')
  1443. ->willReturn(16895);
  1444. $this->assertEquals(
  1445. 777,
  1446. $path->getPermissions()
  1447. );
  1448. }
  1449. /**
  1450. * @throws IOException
  1451. * @throws FileNotFoundException
  1452. */
  1453. public function testGetPermissionsFileDoesNotExist(): void
  1454. {
  1455. $path = $this->getMock('/foo/file.ext', 'getPermissions');
  1456. $path->method('isFile')->willReturn(False);
  1457. $this->builtin
  1458. ->expects(self::never())
  1459. ->method('fileperms');
  1460. $this->expectException(FileNotFoundException::class);
  1461. $path->getPermissions();
  1462. }
  1463. /**
  1464. * @throws IOException
  1465. * @throws FileNotFoundException
  1466. */
  1467. public function testGetPermissionsWithError(): void
  1468. {
  1469. $path = $this->getMock('/foo/file.ext', 'getPermissions');
  1470. $path->method('isFile')->willReturn(True);
  1471. $this->builtin
  1472. ->method('fileperms')
  1473. ->with('/foo/file.ext')
  1474. ->willReturn(False);
  1475. $this->expectException(IOException::class);
  1476. $path->getPermissions();
  1477. }
  1478. /**
  1479. * @throws FileNotFoundException|IOException
  1480. */
  1481. public function testSetPermissions(): void
  1482. {
  1483. $path = $this->getMock('/foo/file.ext', 'setPermissions');
  1484. $path->method('isFile')->willReturn(True);
  1485. $this->builtin
  1486. ->method('chmod')
  1487. ->with('/foo/file.ext', 0777)
  1488. ->willReturn(True);
  1489. $this->builtin
  1490. ->expects(self::once())
  1491. ->method('clearstatcache');
  1492. $path->setPermissions(0777);
  1493. }
  1494. /**
  1495. * @throws FileNotFoundException|IOException
  1496. */
  1497. public function testSetPermissionsFileDoesNotExist(): void
  1498. {
  1499. $path = $this->getMock('/foo/file.ext', 'setPermissions');
  1500. $path->method('isFile')->willReturn(False);
  1501. $this->builtin
  1502. ->expects(self::never())
  1503. ->method('clearstatcache');
  1504. $this->builtin
  1505. ->expects(self::never())
  1506. ->method('chmod');
  1507. $this->expectException(FileNotFoundException::class);
  1508. $path->setPermissions(0777);
  1509. }
  1510. /**
  1511. * @throws FileNotFoundException
  1512. */
  1513. public function testSetPermissionsWithError(): void
  1514. {
  1515. $path = $this->getMock('/foo/file.ext', 'setPermissions');
  1516. $path->method('isFile')->willReturn(True);
  1517. $this->builtin
  1518. ->expects(self::once())
  1519. ->method('clearstatcache');
  1520. $this->builtin
  1521. ->method('chmod')
  1522. ->with('/foo/file.ext', 0777)
  1523. ->willReturn(False);
  1524. $this->expectException(IOException::class);
  1525. $path->setPermissions(0777);
  1526. }
  1527. /**
  1528. * @throws FileNotFoundException
  1529. * @throws IOException
  1530. */
  1531. public function testSetOwner(): void
  1532. {
  1533. $path = $this->getMock('/foo/file.ext', 'setOwner');
  1534. $path->method('isFile')->willReturn(True);
  1535. $this->builtin
  1536. ->expects(self::once())
  1537. ->method('clearstatcache');
  1538. $this->builtin
  1539. ->method('chown')
  1540. ->with('/foo/file.ext', 'user')
  1541. ->willReturn(True);
  1542. $this->builtin
  1543. ->method('chgrp')
  1544. ->with('/foo/file.ext', 'group')
  1545. ->willReturn(True);
  1546. $path->setOwner('user', 'group');
  1547. }
  1548. /**
  1549. * @throws FileNotFoundException|IOException
  1550. */
  1551. public function testSetOwnerFileDoesNotExist(): void
  1552. {
  1553. $path = $this->getMock('/foo/file.ext', 'setOwner');
  1554. $path->method('isFile')->willReturn(False);
  1555. $this->builtin
  1556. ->expects(self::never())
  1557. ->method('clearstatcache');
  1558. $this->builtin
  1559. ->expects(self::never())
  1560. ->method('chown');
  1561. $this->builtin
  1562. ->expects(self::never())
  1563. ->method('chgrp');
  1564. $this->expectException(FileNotFoundException::class);
  1565. $path->setOwner('user', 'group');
  1566. }
  1567. /**
  1568. * @throws FileNotFoundException
  1569. */
  1570. public function testSetPermissionsWithChownError(): void
  1571. {
  1572. $path = $this->getMock('/foo/file.ext', 'setOwner');
  1573. $path->method('isFile')->willReturn(True);
  1574. $this->builtin
  1575. ->expects(self::once())
  1576. ->method('clearstatcache');
  1577. $this->builtin
  1578. ->method('chown')
  1579. ->with('/foo/file.ext', 'user')
  1580. ->willReturn(False);
  1581. $this->builtin
  1582. ->method('chgrp')
  1583. ->with('/foo/file.ext', 'group')
  1584. ->willReturn(True);
  1585. $this->expectException(IOException::class);
  1586. $path->setOwner('user', 'group');
  1587. }
  1588. /**
  1589. * @throws FileNotFoundException
  1590. */
  1591. public function testSetPermissionsWithChGroupError(): void
  1592. {
  1593. $path = $this->getMock('/foo/file.ext', 'setOwner');
  1594. $path->method('isFile')->willReturn(True);
  1595. $this->builtin
  1596. ->method('chown')
  1597. ->with('/foo/file.ext', 'user')
  1598. ->willReturn(True);
  1599. $this->builtin
  1600. ->method('chgrp')
  1601. ->with('/foo/file.ext', 'group')
  1602. ->willReturn(False);
  1603. $this->expectException(IOException::class);
  1604. $path->setOwner('user', 'group');
  1605. }
  1606. public function testExists(): void
  1607. {
  1608. $path = $this->getMock('/foo/file.ext', 'exists');
  1609. $this->builtin
  1610. ->expects(self::once())
  1611. ->method('file_exists')
  1612. ->with('/foo/file.ext')
  1613. ->willReturn(True);
  1614. $this->assertTrue(
  1615. $path->exists()
  1616. );
  1617. }
  1618. /**
  1619. * @throws IOException
  1620. * @throws FileNotFoundException
  1621. */
  1622. public function testGlob(): void {
  1623. $path = $this->getMock('/foo', 'glob');
  1624. $path->method('isDir')->willReturn(True);
  1625. $this->builtin
  1626. ->expects(self::once())
  1627. ->method('glob')
  1628. ->with('/foo/*')
  1629. ->willReturn(['a', 'b', 'c']);
  1630. $this->assertEquals(
  1631. ['a', 'b', 'c'],
  1632. array_map(
  1633. function (Path $p) { return (string)$p; },
  1634. $path->glob('*')
  1635. )
  1636. );
  1637. }
  1638. /**
  1639. * @throws IOException
  1640. */
  1641. public function testGlobDirDoesNotExist(): void {
  1642. $path = $this->getMock('/foo', 'glob');
  1643. $path->method('isDir')->willReturn(False);
  1644. $this->builtin
  1645. ->expects(self::never())
  1646. ->method('glob');
  1647. $this->expectException(FileNotFoundException::class);
  1648. $path->glob('*');
  1649. }
  1650. /**
  1651. * @throws FileNotFoundException
  1652. */
  1653. public function testGlobWithError(): void {
  1654. $path = $this->getMock('/foo', 'glob');
  1655. $path->method('isDir')->willReturn(True);
  1656. $this->builtin
  1657. ->expects(self::once())
  1658. ->method('glob')
  1659. ->with('/foo/*')
  1660. ->willReturn(False);
  1661. $this->expectException(IOException::class);
  1662. $path->glob('*');
  1663. }
  1664. /**
  1665. * @throws FileNotFoundException
  1666. * @throws IOException
  1667. */
  1668. public function testRmDirNonRecursive(): void
  1669. {
  1670. $path = $this->getMock('/foo', 'rmdir');
  1671. $path->method('isDir')->willReturn(True);
  1672. $this->builtin
  1673. ->method('rmdir')
  1674. ->with('/foo')
  1675. ->willReturn(True);
  1676. $path
  1677. ->expects(self::never())
  1678. ->method('rrmdir');
  1679. $path->rmdir();
  1680. }
  1681. /**
  1682. * @throws FileNotFoundException
  1683. * @throws IOException
  1684. */
  1685. public function testRmDirRecursive(): void
  1686. {
  1687. $path = $this->getMock('/foo', 'rmdir');
  1688. $path->method('isDir')->willReturn(True);
  1689. $this->builtin
  1690. ->expects(self::never())
  1691. ->method('rmdir');
  1692. $path
  1693. ->method('rrmdir')
  1694. ->willReturn(True);
  1695. $path->rmdir(True);
  1696. }
  1697. /**
  1698. * @throws IOException
  1699. * @throws FileNotFoundException
  1700. */
  1701. public function testOpen(): void
  1702. {
  1703. $path = $this->getMock('/foo/file.ext', 'open');
  1704. $path->method('isFile')->willReturn(True);
  1705. $this->builtin
  1706. ->expects(self::once())
  1707. ->method('fopen')
  1708. ->with('/foo/file.ext', 'r')
  1709. ->willReturn('the_handle');
  1710. $this->assertEquals(
  1711. 'the_handle',
  1712. $path->open()
  1713. );
  1714. }
  1715. /**
  1716. * @throws IOException
  1717. * @throws FileNotFoundException
  1718. */
  1719. public function testOpenWithMode(): void
  1720. {
  1721. $path = $this->getMock('/foo/file.ext', 'open');
  1722. $path->method('isFile')->willReturn(True);
  1723. $this->builtin
  1724. ->expects(self::once())
  1725. ->method('fopen')
  1726. ->with('/foo/file.ext', 'w')
  1727. ->willReturn('the_handle');
  1728. $this->assertEquals(
  1729. 'the_handle',
  1730. $path->open('w')
  1731. );
  1732. }
  1733. /**
  1734. * @throws IOException
  1735. * @throws FileNotFoundException
  1736. */
  1737. public function testOpenFileDoesNotExist(): void
  1738. {
  1739. $path = $this->getMock('/foo/file.ext', 'open');
  1740. $path->method('isFile')->willReturn(False);
  1741. $this->builtin
  1742. ->expects(self::never())
  1743. ->method('fopen');
  1744. $this->expectException(FileNotFoundException::class);
  1745. $path->open();
  1746. }
  1747. /**
  1748. * @throws IOException
  1749. * @throws FileNotFoundException
  1750. */
  1751. public function testOpenWithError(): void
  1752. {
  1753. $path = $this->getMock('/foo/file.ext', 'open');
  1754. $path->method('isFile')->willReturn(True);
  1755. $this->builtin
  1756. ->expects(self::once())
  1757. ->method('fopen')
  1758. ->with('/foo/file.ext', 'r')
  1759. ->willReturn(False);
  1760. $this->expectException(IOException::class);
  1761. $path->open();
  1762. }
  1763. /**
  1764. * @throws \Throwable
  1765. */
  1766. public function testWith(): void
  1767. {
  1768. $path = $this->getMock('/foo/file.ext', 'with');
  1769. $path->method('open')->with('r')->willReturn('the_handle');
  1770. $callback = function ($handle) {
  1771. $this->assertEquals('the_handle', $handle);
  1772. return 'content';
  1773. };
  1774. $this->builtin
  1775. ->expects(self::once())
  1776. ->method('fclose')
  1777. ->with('the_handle')
  1778. ->willReturn(True);
  1779. $this->assertEquals(
  1780. 'content',
  1781. $path->with($callback)
  1782. );
  1783. }
  1784. /**
  1785. * @throws \Throwable
  1786. */
  1787. public function testWithWithMode(): void
  1788. {
  1789. $path = $this->getMock('/foo/file.ext', 'with');
  1790. $path->method('open')->with('w+')->willReturn('the_handle');
  1791. $callback = function ($handle) {
  1792. $this->assertEquals('the_handle', $handle);
  1793. return 'content';
  1794. };
  1795. $this->builtin
  1796. ->expects(self::once())
  1797. ->method('fclose')
  1798. ->with('the_handle')
  1799. ->willReturn(True);
  1800. $this->assertEquals(
  1801. 'content',
  1802. $path->with($callback, 'w+')
  1803. );
  1804. }
  1805. /**
  1806. * @throws \Throwable
  1807. */
  1808. public function testWithWithCallbackError(): void
  1809. {
  1810. $path = $this->getMock('/foo/file.ext', 'with');
  1811. $path->method('open')->with('w+')->willReturn('the_handle');
  1812. $callback = function ($handle) {
  1813. $this->assertEquals('the_handle', $handle);
  1814. throw new \Exception('some_error');
  1815. };
  1816. $this->builtin
  1817. ->expects(self::once())
  1818. ->method('fclose')
  1819. ->with('the_handle')
  1820. ->willReturn(True);
  1821. $this->expectException(\Exception::class);
  1822. $path->with($callback, 'w+');
  1823. }
  1824. /**
  1825. * @throws \Throwable
  1826. */
  1827. public function testWithWithCallbackErrorAndClosingError(): void
  1828. {
  1829. $path = $this->getMock('/foo/file.ext', 'with');
  1830. $path->method('open')->with('w+')->willReturn('the_handle');
  1831. $callback = function ($handle) {
  1832. $this->assertEquals('the_handle', $handle);
  1833. throw new \Exception('some_error');
  1834. };
  1835. $this->builtin
  1836. ->expects(self::once())
  1837. ->method('fclose')
  1838. ->with('the_handle')
  1839. ->willReturn(False);
  1840. $this->expectException(\Exception::class);
  1841. $this->expectException(IOException::class);
  1842. $path->with($callback, 'w+');
  1843. }
  1844. /**
  1845. * @throws IOException
  1846. * @throws FileNotFoundException
  1847. * @throws \Throwable
  1848. */
  1849. public function testChunks(): void
  1850. {
  1851. $path = $this->getMock('/foo/file.ext', 'chunks');
  1852. $path->method('open')->with('rb')->willReturn('the_handle');
  1853. $this->builtin
  1854. ->method('feof')
  1855. ->with('the_handle')
  1856. ->willReturnOnConsecutiveCalls(
  1857. False,
  1858. False,
  1859. False,
  1860. True
  1861. );
  1862. $this->builtin
  1863. ->method('fread')
  1864. ->with('the_handle', 8192)
  1865. ->willReturnOnConsecutiveCalls(
  1866. 'abc',
  1867. 'def',
  1868. 'ghi'
  1869. );
  1870. $this->builtin
  1871. ->expects(self::once())
  1872. ->method('fclose')
  1873. ->with('the_handle')
  1874. ->willReturn(True);
  1875. $this->assertEquals(
  1876. ['abc', 'def', 'ghi'],
  1877. iterator_to_array($path->chunks())
  1878. );
  1879. }
  1880. /**
  1881. * @throws IOException
  1882. * @throws FileNotFoundException
  1883. * @throws \Throwable
  1884. */
  1885. public function testChunksWithDifferentLength(): void
  1886. {
  1887. $path = $this->getMock('/foo/file.ext', 'chunks');
  1888. $path->method('open')->with('rb')->willReturn('the_handle');
  1889. $this->builtin
  1890. ->method('feof')
  1891. ->with('the_handle')
  1892. ->willReturnOnConsecutiveCalls(
  1893. False,
  1894. False,
  1895. False,
  1896. True
  1897. );
  1898. $this->builtin
  1899. ->method('fread')
  1900. ->with('the_handle', 123)
  1901. ->willReturnOnConsecutiveCalls(
  1902. 'abc',
  1903. 'def',
  1904. 'ghi'
  1905. );
  1906. $this->builtin
  1907. ->expects(self::once())
  1908. ->method('fclose')
  1909. ->with('the_handle')
  1910. ->willReturn(True);
  1911. $this->assertEquals(
  1912. ['abc', 'def', 'ghi'],
  1913. iterator_to_array($path->chunks(123))
  1914. );
  1915. }
  1916. /**
  1917. * @throws \Throwable
  1918. */
  1919. public function testChunksWithClosingError(): void
  1920. {
  1921. $path = $this->getMock('/foo/file.ext', 'chunks');
  1922. $path->method('open')->with('rb')->willReturn('the_handle');
  1923. $this->builtin
  1924. ->method('feof')
  1925. ->with('the_handle')
  1926. ->willReturnOnConsecutiveCalls(
  1927. False,
  1928. False,
  1929. False,
  1930. True
  1931. );
  1932. $this->builtin
  1933. ->method('fread')
  1934. ->with('the_handle', 8192)
  1935. ->willReturnOnConsecutiveCalls(
  1936. 'abc',
  1937. 'def',
  1938. 'ghi'
  1939. );
  1940. $this->builtin
  1941. ->expects(self::once())
  1942. ->method('fclose')
  1943. ->with('the_handle')
  1944. ->willReturn(False);
  1945. $this->expectException(IOException::class);
  1946. iterator_to_array($path->chunks());
  1947. }
  1948. public function testIsAbs(): void
  1949. {
  1950. $path = $this->getMock('/foo/file.ext', 'isAbs');
  1951. $this->assertTrue(
  1952. $path->isAbs()
  1953. );
  1954. }
  1955. public function testIsAbsWithRelative(): void
  1956. {
  1957. $path = $this->getMock('foo/file.ext', 'isAbs');
  1958. $this->assertFalse(
  1959. $path->isAbs()
  1960. );
  1961. }
  1962. /**
  1963. * @throws IOException
  1964. * @throws FileNotFoundException
  1965. */
  1966. public function testChmod(): void
  1967. {
  1968. $path = $this->getMock('foo/file.ext', 'chmod');
  1969. $path
  1970. ->expects(self::once())
  1971. ->method('setPermissions')
  1972. ->with('777');
  1973. $path->chmod(777);
  1974. }
  1975. /**
  1976. * @throws IOException
  1977. * @throws FileNotFoundException
  1978. */
  1979. public function testChown(): void
  1980. {
  1981. $path = $this->getMock('foo/file.ext', 'chown');
  1982. $path
  1983. ->expects(self::once())
  1984. ->method('setOwner')
  1985. ->with('user', 'group');
  1986. $path->chown('user', 'group');
  1987. }
  1988. /**
  1989. * @throws IOException
  1990. */
  1991. public function testChRoot(): void
  1992. {
  1993. $path = $this->getMock('/foo', 'chroot');
  1994. $this->builtin
  1995. ->expects(self::once())
  1996. ->method('chroot')
  1997. ->with('/foo')
  1998. ->willReturn(True);
  1999. $path->chroot();
  2000. }
  2001. /**
  2002. * @throws IOException
  2003. */
  2004. public function testChRootWithError(): void
  2005. {
  2006. $path = $this->getMock('/foo', 'chroot');
  2007. $this->builtin
  2008. ->expects(self::once())
  2009. ->method('chroot')
  2010. ->with('/foo')
  2011. ->willReturn(False);
  2012. $this->expectException(IOException::class);
  2013. $path->chroot();
  2014. }
  2015. public function testIsLink(): void
  2016. {
  2017. $path = $this->getMock('/foo/file.ext', 'isLink');
  2018. $this->builtin
  2019. ->expects(self::once())
  2020. ->method('is_link')
  2021. ->with('/foo/file.ext')
  2022. ->willReturn(True);
  2023. $this->assertTrue(
  2024. $path->isLink()
  2025. );
  2026. }
  2027. public function testIsLinkIsNot(): void
  2028. {
  2029. $path = $this->getMock('/foo/file.ext', 'isLink');
  2030. $this->builtin
  2031. ->expects(self::once())
  2032. ->method('is_link')
  2033. ->with('/foo/file.ext')
  2034. ->willReturn(False);
  2035. $this->assertFalse(
  2036. $path->isLink()
  2037. );
  2038. }
  2039. /**
  2040. * @throws FileNotFoundException
  2041. */
  2042. public function testIterDir(): void
  2043. {
  2044. $path = $this->getMock('/foo', 'iterDir');
  2045. $path->method('isDir')->willReturn(True);
  2046. $fileInfo1 = $this->getMockBuilder(\DirectoryIterator::class)->disableOriginalConstructor()->getMock();
  2047. $fileInfo1->expects(self::once())->method('isDot')->willReturn(True);
  2048. $fileInfo1->expects(self::never())->method('getFilename');
  2049. $fileInfo2 = $this->getMockBuilder(\DirectoryIterator::class)->disableOriginalConstructor()->getMock();
  2050. $fileInfo2->expects(self::once())->method('isDot')->willReturn(False);
  2051. $fileInfo2->expects(self::once())->method('getFilename')->willReturn('file1.ext');
  2052. $fileInfo3 = $this->getMockBuilder(\DirectoryIterator::class)->disableOriginalConstructor()->getMock();
  2053. $fileInfo3->expects(self::once())->method('isDot')->willReturn(False);
  2054. $fileInfo3->expects(self::once())->method('getFilename')->willReturn('file2.ext');
  2055. $result = [$fileInfo1, $fileInfo2, $fileInfo3];
  2056. $directoryIterator = $this->getMockBuilder(\DirectoryIterator::class)->disableOriginalConstructor()->getMock();
  2057. $directoryIterator->method('current')->willReturnCallback(function () use (&$result) {
  2058. return current($result);
  2059. });
  2060. $directoryIterator->method('key')->willReturnCallback(function () use (&$result) {
  2061. return key($result);
  2062. });
  2063. $directoryIterator->method('next')->willReturnCallback(function () use (&$result) {
  2064. return next($result);
  2065. });
  2066. $directoryIterator->method('valid')->willReturnCallback(function () use (&$result) {
  2067. $key = key($result);
  2068. return ($key !== NULL);
  2069. });
  2070. $path
  2071. ->method('getDirectoryIterator')
  2072. ->willReturn($directoryIterator);
  2073. $this->assertEquals(
  2074. ['file1.ext', 'file2.ext'],
  2075. iterator_to_array($path->iterDir())
  2076. );
  2077. }
  2078. /**
  2079. * @throws FileNotFoundException
  2080. */
  2081. public function testIterDirDirDoesNotExist(): void
  2082. {
  2083. $path = $this->getMock('/foo', 'iterDir');
  2084. $path->method('isDir')->willReturn(False);
  2085. $this->expectException(FileNotFoundException::class);
  2086. iterator_to_array($path->iterDir());
  2087. }
  2088. /**
  2089. * @throws IOException
  2090. * @throws FileNotFoundException
  2091. * @throws FileExistsException
  2092. */
  2093. public function testLink(): void
  2094. {
  2095. $path = $this->getMock('/foo/file.ext', 'link');
  2096. $path->method('isFile')->willReturn(True);
  2097. $target = $this
  2098. ->getMockBuilder(TestablePath::class)
  2099. ->disableOriginalConstructor()
  2100. ->getMock();
  2101. $target->method('isFile')->willReturn(False);
  2102. $target->method('__toString')->willReturn('/bar/link.ext');
  2103. $path->method('cast')->with($target)->willReturn($target);
  2104. $this->builtin
  2105. ->expects(self::once())
  2106. ->method('link')
  2107. ->with('/foo/file.ext', '/bar/link.ext')
  2108. ->willReturn(True);
  2109. $path->link($target);
  2110. }
  2111. /**
  2112. * @throws IOException
  2113. * @throws FileNotFoundException
  2114. * @throws FileExistsException
  2115. */
  2116. public function testLinkWithStringTarget(): void
  2117. {
  2118. $path = $this->getMock('/foo/file.ext', 'link');
  2119. $path->method('isFile')->willReturn(True);
  2120. $target = $this
  2121. ->getMockBuilder(TestablePath::class)
  2122. ->disableOriginalConstructor()
  2123. ->getMock();
  2124. $target->method('isFile')->willReturn(False);
  2125. $target->method('__toString')->willReturn('/bar/link.ext');
  2126. $path->method('cast')->with('/bar/link.ext')->willReturn($target);
  2127. $this->builtin
  2128. ->expects(self::once())
  2129. ->method('link')
  2130. ->with('/foo/file.ext', '/bar/link.ext')
  2131. ->willReturn(True);
  2132. $path->link($target);
  2133. }
  2134. /**
  2135. * @throws IOException
  2136. * @throws FileNotFoundException
  2137. * @throws FileExistsException
  2138. */
  2139. public function testLinkFileDoesNotExist(): void
  2140. {
  2141. $path = $this->getMock('/foo/file.ext', 'link');
  2142. $path->method('isFile')->willReturn(False);
  2143. $this->builtin
  2144. ->expects(self::never())
  2145. ->method('link');
  2146. $this->expectException(FileNotFoundException::class);
  2147. $path->link('/bar/link.ext');
  2148. }
  2149. /**
  2150. * @throws IOException
  2151. * @throws FileNotFoundException
  2152. * @throws FileExistsException
  2153. */
  2154. public function testLinkTargetExists(): void
  2155. {
  2156. $path = $this->getMock('/foo/file.ext', 'link');
  2157. $path->method('isFile')->willReturn(True);
  2158. $target = $this
  2159. ->getMockBuilder(TestablePath::class)
  2160. ->disableOriginalConstructor()
  2161. ->getMock();
  2162. $target->method('isFile')->willReturn(True);
  2163. $path->method('cast')->with($target)->willReturn($target);
  2164. $this->builtin
  2165. ->expects(self::never())
  2166. ->method('link');
  2167. $this->expectException(FileExistsException::class);
  2168. $path->link($target);
  2169. }
  2170. /**
  2171. * @throws IOException
  2172. * @throws FileNotFoundException
  2173. * @throws FileExistsException
  2174. */
  2175. public function testLinkWithError(): void
  2176. {
  2177. $path = $this->getMock('/foo/file.ext', 'link');
  2178. $path->method('isFile')->willReturn(True);
  2179. $target = $this
  2180. ->getMockBuilder(TestablePath::class)
  2181. ->disableOriginalConstructor()
  2182. ->getMock();
  2183. $target->method('isFile')->willReturn(False);
  2184. $target->method('__toString')->willReturn('/bar/link.ext');
  2185. $path->method('cast')->with($target)->willReturn($target);
  2186. $this->builtin
  2187. ->expects(self::once())
  2188. ->method('link')
  2189. ->with('/foo/file.ext', '/bar/link.ext')
  2190. ->willReturn(False);
  2191. $this->expectException(IOException::class);
  2192. $path->link($target);
  2193. }
  2194. /**
  2195. * @throws IOException
  2196. */
  2197. public function testLStat(): void
  2198. {
  2199. $path = $this->getMock('foo/file.ext', 'lstat');
  2200. $this->builtin
  2201. ->expects(self::once())
  2202. ->method('lstat')
  2203. ->willReturn(['a', 'b', 'c']);
  2204. $this->assertEquals(
  2205. ['a', 'b', 'c'],
  2206. $path->lstat()
  2207. );
  2208. }
  2209. /**
  2210. * @throws IOException
  2211. */
  2212. public function testLStatWithError(): void
  2213. {
  2214. $path = $this->getMock('foo/file.ext', 'lstat');
  2215. $this->builtin
  2216. ->expects(self::once())
  2217. ->method('lstat')
  2218. ->willReturn(False);
  2219. $this->expectException(IOException::class);
  2220. $path->lstat();
  2221. }
  2222. public function testParts(): void
  2223. {
  2224. $path = $this->getMock('foo/bar/file.ext', 'parts');
  2225. $this->assertEquals(
  2226. ['foo', 'bar', 'file.ext'],
  2227. $path->parts()
  2228. );
  2229. }
  2230. public function testPartsWithLeadingSlash(): void
  2231. {
  2232. $path = $this->getMock('/foo/bar/file.ext', 'parts');
  2233. $this->assertEquals(
  2234. ['/', 'foo', 'bar', 'file.ext'],
  2235. $path->parts()
  2236. );
  2237. }
  2238. /**
  2239. * @throws IOException
  2240. * @throws FileNotFoundException
  2241. */
  2242. public function testGetRelativePath(): void
  2243. {
  2244. $path = $this->getMock('./bar/file.ext', 'getRelativePath');
  2245. $path->method('exists')->willReturn(True);
  2246. $absPath = $this
  2247. ->getMockBuilder(TestablePath::class)
  2248. ->disableOriginalConstructor()
  2249. ->getMock();
  2250. $absPath->method('__toString')->willReturn('/foo/bar/file.ext');
  2251. $path->method('absPath')->willReturn($absPath);
  2252. $basePath = '/other/path';
  2253. $this->builtin
  2254. ->expects(self::once())
  2255. ->method('realpath')
  2256. ->with($basePath)
  2257. ->willReturn('/other/path');
  2258. $this->assertEquals(
  2259. '../../foo/bar/file.ext',
  2260. $path->getRelativePath($basePath)
  2261. );
  2262. }
  2263. /**
  2264. * @throws IOException
  2265. * @throws FileNotFoundException
  2266. */
  2267. public function testGetRelativePathFileDoesNotExist(): void
  2268. {
  2269. $path = $this->getMock('./bar/file.ext', 'getRelativePath');
  2270. $path->method('exists')->willReturn(False);
  2271. $this->expectException(FileNotFoundException::class);
  2272. $path->getRelativePath('/other/path');
  2273. }
  2274. /**
  2275. * @throws IOException
  2276. * @throws FileNotFoundException
  2277. */
  2278. public function testGetRelativePathTargetDoesNotExist(): void
  2279. {
  2280. $path = $this->getMock('./bar/file.ext', 'getRelativePath');
  2281. $path->method('exists')->willReturn(True);
  2282. $absPath = $this
  2283. ->getMockBuilder(TestablePath::class)
  2284. ->disableOriginalConstructor()
  2285. ->getMock();
  2286. $absPath->method('__toString')->willReturn('/foo/bar/file.ext');
  2287. $path->method('absPath')->willReturn($absPath);
  2288. $basePath = '/other/path';
  2289. $this->builtin
  2290. ->expects(self::once())
  2291. ->method('realpath')
  2292. ->with($basePath)
  2293. ->willReturn(False);
  2294. $this->expectException(FileNotFoundException::class);
  2295. $path->getRelativePath($basePath);
  2296. }
  2297. }