CommandLine.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. use PHPUnit\Framework\Assert;
  8. require __DIR__ . '/../../vendor/autoload.php';
  9. trait CommandLine {
  10. /** @var int return code of last command */
  11. private $lastCode;
  12. /** @var string stdout of last command */
  13. private $lastStdOut;
  14. /** @var string stderr of last command */
  15. private $lastStdErr;
  16. /** @var string */
  17. protected $ocPath = '../..';
  18. /**
  19. * Invokes an OCC command
  20. *
  21. * @param []string $args OCC command, the part behind "occ". For example: "files:transfer-ownership"
  22. * @return int exit code
  23. */
  24. public function runOcc($args = []) {
  25. $args = array_map(function ($arg) {
  26. return escapeshellarg($arg);
  27. }, $args);
  28. $args[] = '--no-ansi';
  29. $args = implode(' ', $args);
  30. $descriptor = [
  31. 0 => ['pipe', 'r'],
  32. 1 => ['pipe', 'w'],
  33. 2 => ['pipe', 'w'],
  34. ];
  35. $process = proc_open('php console.php ' . $args, $descriptor, $pipes, $this->ocPath);
  36. $this->lastStdOut = stream_get_contents($pipes[1]);
  37. $this->lastStdErr = stream_get_contents($pipes[2]);
  38. $this->lastCode = proc_close($process);
  39. // Clean opcode cache
  40. $client = new GuzzleHttp\Client();
  41. $client->request('GET', 'http://localhost:8080/apps/testing/clean_opcode_cache.php');
  42. return $this->lastCode;
  43. }
  44. /**
  45. * @Given /^invoking occ with "([^"]*)"$/
  46. */
  47. public function invokingTheCommand($cmd) {
  48. $args = explode(' ', $cmd);
  49. $this->runOcc($args);
  50. }
  51. /**
  52. * Find exception texts in stderr
  53. */
  54. public function findExceptions() {
  55. $exceptions = [];
  56. $captureNext = false;
  57. // the exception text usually appears after an "[Exception"] row
  58. foreach (explode("\n", $this->lastStdErr) as $line) {
  59. if (preg_match('/\[Exception\]/', $line)) {
  60. $captureNext = true;
  61. continue;
  62. }
  63. if ($captureNext) {
  64. $exceptions[] = trim($line);
  65. $captureNext = false;
  66. }
  67. }
  68. return $exceptions;
  69. }
  70. /**
  71. * @Then /^the command was successful$/
  72. */
  73. public function theCommandWasSuccessful() {
  74. $exceptions = $this->findExceptions();
  75. if ($this->lastCode !== 0) {
  76. $msg = 'The command was not successful, exit code was ' . $this->lastCode . '.';
  77. if (!empty($exceptions)) {
  78. $msg .= ' Exceptions: ' . implode(', ', $exceptions);
  79. }
  80. throw new \Exception($msg);
  81. } elseif (!empty($exceptions)) {
  82. $msg = 'The command was successful but triggered exceptions: ' . implode(', ', $exceptions);
  83. throw new \Exception($msg);
  84. }
  85. }
  86. /**
  87. * @Then /^the command failed with exit code ([0-9]+)$/
  88. */
  89. public function theCommandFailedWithExitCode($exitCode) {
  90. if ($this->lastCode !== (int)$exitCode) {
  91. throw new \Exception('The command was expected to fail with exit code ' . $exitCode . ' but got ' . $this->lastCode);
  92. }
  93. }
  94. /**
  95. * @Then /^the command failed with exception text "([^"]*)"$/
  96. */
  97. public function theCommandFailedWithException($exceptionText) {
  98. $exceptions = $this->findExceptions();
  99. if (empty($exceptions)) {
  100. throw new \Exception('The command did not throw any exceptions');
  101. }
  102. if (!in_array($exceptionText, $exceptions)) {
  103. throw new \Exception('The command did not throw any exception with the text "' . $exceptionText . '"');
  104. }
  105. }
  106. /**
  107. * @Then /^the command output contains the text "([^"]*)"$/
  108. */
  109. public function theCommandOutputContainsTheText($text) {
  110. Assert::assertStringContainsString($text, $this->lastStdOut, 'The command did not output the expected text on stdout');
  111. }
  112. /**
  113. * @Then /^the command error output contains the text "([^"]*)"$/
  114. */
  115. public function theCommandErrorOutputContainsTheText($text) {
  116. Assert::assertStringContainsString($text, $this->lastStdErr, 'The command did not output the expected text on stderr');
  117. }
  118. }