From 0d8d5740b1f8b782e7da77ecf9ebd865e62d5629 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Thu, 21 Nov 2019 13:58:38 -0800 Subject: [PATCH] (dev/core#1412) E2E - Add test case for path+URL construction in CLI Overview -------- In dev/core#1412, the regression involved CLI processes producing incorrect URLs. This adds some test-coverage. Before ------ No test coverage for URLs in CLI environment. After ----- There is some test-coverage. It's able to reveal the existence of the bug from 1412. Comments -------- A lot of path/URL construction is dependent on the environment/site-build. The test does not, on its own, guarantee that all environments work. Rather, it adds a new slice of cheese to the stack. This slice is moderately generic - in that I've successfully tested it localy on `drupal-demo` and `wp-demo` builds. In theory, it should work on other build types (as long as they set variables `CIVI_CORE`, `CMS_ROOT`, `CMS_URL`). --- tests/phpunit/E2E/Extern/CliRunnerTest.php | 170 +++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 tests/phpunit/E2E/Extern/CliRunnerTest.php diff --git a/tests/phpunit/E2E/Extern/CliRunnerTest.php b/tests/phpunit/E2E/Extern/CliRunnerTest.php new file mode 100644 index 0000000000..ce23acc46a --- /dev/null +++ b/tests/phpunit/E2E/Extern/CliRunnerTest.php @@ -0,0 +1,170 @@ +markTestSkipped("Test environment does provide the civibuild/cv variable ($var)"); + } + } + } + + protected function tearDown() { + parent::tearDown(); + } + + /** + * @return array + * Each case gives a name (eg "cv") and template for executing the command + * (eg "cv ev @PHP"). + */ + public function getRunners() { + $cliRunners = []; + + if (CIVICRM_UF === 'WordPress') { + $cliRunners['wp'] = ['wp', 'wp eval \'civicrm_initialize();\'@PHP']; + } + if (CIVICRM_UF === 'Drupal' || CIVICRM_UF === 'Backdrop') { + $cliRunners['drush'] = ['drush', 'drush ev \'civicrm_initialize();\'@PHP']; + } + // TODO: Drupal8 w/drush (doesn't use civicrm_initialize?) + + $cliRunners['cv'] = ['cv', 'cv ev @PHP']; + + return $cliRunners; + } + + public function getRunnersAndPaths() { + $exs = []; + foreach ($this->getRunners() as $runner) { + $exs[] = array_merge($runner, ['[civicrm.root]/css/civicrm.css']); + $exs[] = array_merge($runner, ['[civicrm.packages]/jquery/css/images/arrow.png']); + } + return $exs; + } + + /** + * @param string $name + * The name of the command we're testing with. + * Ex: 'cv' + * @param string $r + * Ex: 'cv ev @PHP' + * @dataProvider getRunners + */ + public function testBasicPathUrl($name, $r) { + $this->assertNotEmpty($this->findCommand($name), 'The command "$name" does not appear in the PATH.'); + + $cv = $GLOBALS['_CV']; + $this->assertEquals($cv['CIVI_CORE'], $this->callRunnerJson($r, '$GLOBALS[\'civicrm_root\']')); + $this->assertEquals($cv['CMS_URL'] . 'foo', $this->callRunnerJson($r, 'Civi::paths()->getUrl(\'[cms.root]/foo\')')); + $this->assertEquals($cv['CMS_ROOT'] . 'foo', $this->callRunnerJson($r, 'Civi::paths()->getPath(\'[cms.root]/foo\')')); + $this->assertEquals($cv['CIVI_CORE'] . 'css/civicrm.css', $this->callRunnerJson($r, 'Civi::paths()->getPath(\'[civicrm.root]/css/civicrm.css\')')); + + $ufrUrl = $this->callRunnerJson($r, 'CRM_Core_Config::singleton()->userFrameworkResourceURL'); + $crmUrl = $this->callRunnerJson($r, 'Civi::paths()->getUrl("[civicrm.root]/.")'); + $this->assertEquals($crmUrl, $ufrUrl); + } + + /** + * For some URLs, we don't have a good environment variable for predicting the URL. + * Instead, we'll just see if the generated URLs match the generated paths. + * + * @param string $name + * The name of the command we're testing with. + * Ex: 'cv' + * @param string $r + * Ex: 'cv ev @PHP' + * @param string $fileExpr + * Ex: '[civicrm.root]/LICENSE' + * @dataProvider getRunnersAndPaths + */ + public function testPathUrlMatch($name, $r, $fileExpr) { + $this->assertNotEmpty($this->findCommand($name), 'The command "$name" does not appear in the PATH.'); + $localPath = $this->callRunnerJson($r, "Civi::paths()->getPath('$fileExpr')"); + $remoteUrl = $this->callRunnerJson($r, "Civi::paths()->getUrl('$fileExpr')"); + $this->assertFileExists($localPath); + $localContent = file_get_contents($localPath); + $this->assertNotEmpty($localContent); + $this->assertEquals($localContent, file_get_contents($remoteUrl), + "civicrm.css should yield same content via local path ($localPath) or HTTP URL ($remoteUrl)" + ); + } + + /** + * @param string $runner + * Ex: 'cv ev @PHP' + * @param string $phpExpr + * PHP expression to evaluate and return. (Encoded+decoded as JSON) + * @return mixed + * The result of running $phpExpr through the given $runner. + */ + protected function callRunnerJson($runner, $phpExpr) { + $json = $this->callRunnerOk($runner, "echo json_encode($phpExpr);"); + return json_decode($json); + } + + /** + * @param string $runner + * Ex: 'cv ev @PHP' + * @param string $phpStmt + * PHP code to execute + * @return string + * The console output of running $phpStmt through the given $runner. + */ + protected function callRunnerOk($runner, $phpStmt) { + $cmd = strtr($runner, ['@PHP' => escapeshellarg($phpStmt)]); + exec($cmd, $output, $val); + $this->assertEquals(0, $val, "Command returned error ($cmd) ($val)"); + return implode("", $output); + } + + protected function findCommand($name) { + $paths = explode(PATH_SEPARATOR, getenv('PATH')); + foreach ($paths as $path) { + if (file_exists("$path/$name")) { + return "$path/$name"; + } + } + return NULL; + } + +} -- 2.25.1