3 +--------------------------------------------------------------------+
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2020 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License along with this program; if not, contact CiviCRM LLC |
21 | at info[AT]civicrm[DOT]org. If you have questions about the |
22 | GNU Affero General Public License or the licensing of CiviCRM, |
23 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
24 +--------------------------------------------------------------------+
28 * Check that various CLI runners are able to bootstrap an environment with
31 * This test assumes that you have built with "civibuild" (or configured cv.json)
32 * to provide canonical/expected values.
34 * It then executes the any supported CLI tools (cv, drush, wp) and checks if
35 * their output matches the expected value.
39 class E2E_Extern_CliRunnerTest
extends CiviEndToEndTestCase
{
41 protected function setUp() {
44 foreach (['CIVI_CORE', 'CMS_ROOT', 'CMS_URL'] as $var) {
45 if (empty($GLOBALS['_CV'][$var])) {
46 $this->markTestSkipped("Test environment does provide the civibuild/cv variable ($var)");
51 protected function tearDown() {
57 * Each case gives a name (eg "cv") and template for executing the command
60 public function getRunners() {
63 if (CIVICRM_UF
=== 'WordPress') {
64 $cliRunners['wp'] = ['wp', 'wp eval \'civicrm_initialize();\'@PHP'];
66 if (CIVICRM_UF
=== 'Drupal' || CIVICRM_UF
=== 'Backdrop') {
67 $cliRunners['drush'] = ['drush', 'drush ev \'civicrm_initialize();\'@PHP'];
69 // TODO: Drupal8 w/drush (doesn't use civicrm_initialize?)
71 $cliRunners['cv'] = ['cv', 'cv ev @PHP'];
76 public function getRunnersAndPaths() {
78 foreach ($this->getRunners() as $runner) {
79 $exs[] = array_merge($runner, ['[civicrm.root]/css/civicrm.css']);
80 $exs[] = array_merge($runner, ['[civicrm.packages]/jquery/css/images/arrow.png']);
87 * The name of the command we're testing with.
91 * @dataProvider getRunners
93 public function testBasicPathUrl($name, $r) {
94 $this->assertNotEmpty($this->findCommand($name), 'The command "$name" does not appear in the PATH.');
96 $cv = $GLOBALS['_CV'];
97 $this->assertEquals($cv['CIVI_CORE'], $this->callRunnerJson($r, '$GLOBALS[\'civicrm_root\']'));
98 $this->assertEquals($cv['CMS_URL'] . 'foo', $this->callRunnerJson($r, 'Civi::paths()->getUrl(\'[cms.root]/foo\')'));
99 $this->assertEquals($cv['CMS_ROOT'] . 'foo', $this->callRunnerJson($r, 'Civi::paths()->getPath(\'[cms.root]/foo\')'));
100 $this->assertEquals($cv['CIVI_CORE'] . 'css/civicrm.css', $this->callRunnerJson($r, 'Civi::paths()->getPath(\'[civicrm.root]/css/civicrm.css\')'));
102 $ufrUrl = $this->callRunnerJson($r, 'CRM_Core_Config::singleton()->userFrameworkResourceURL');
103 $crmUrl = $this->callRunnerJson($r, 'Civi::paths()->getUrl("[civicrm.root]/.")');
104 $this->assertEquals(rtrim($crmUrl, '/'), rtrim($ufrUrl, '/'));
108 * For some URLs, we don't have a good environment variable for predicting the URL.
109 * Instead, we'll just see if the generated URLs match the generated paths.
111 * @param string $name
112 * The name of the command we're testing with.
116 * @param string $fileExpr
117 * Ex: '[civicrm.root]/LICENSE'
118 * @dataProvider getRunnersAndPaths
120 public function testPathUrlMatch($name, $r, $fileExpr) {
121 $this->assertNotEmpty($this->findCommand($name), 'The command "$name" does not appear in the PATH.');
122 $localPath = $this->callRunnerJson($r, "Civi::paths()->getPath('$fileExpr')");
123 $remoteUrl = $this->callRunnerJson($r, "Civi::paths()->getUrl('$fileExpr')");
124 $this->assertFileExists($localPath);
125 $localContent = file_get_contents($localPath);
126 $this->assertNotEmpty($localContent);
127 $this->assertEquals($localContent, file_get_contents($remoteUrl),
128 "civicrm.css should yield same content via local path ($localPath) or HTTP URL ($remoteUrl)"
133 * @param string $runner
135 * @param string $phpExpr
136 * PHP expression to evaluate and return. (Encoded+decoded as JSON)
138 * The result of running $phpExpr through the given $runner.
140 protected function callRunnerJson($runner, $phpExpr) {
141 $json = $this->callRunnerOk($runner, "echo json_encode($phpExpr);");
142 return json_decode($json);
146 * @param string $runner
148 * @param string $phpStmt
149 * PHP code to execute
151 * The console output of running $phpStmt through the given $runner.
153 protected function callRunnerOk($runner, $phpStmt) {
154 $cmd = strtr($runner, ['@PHP' => escapeshellarg($phpStmt)]);
155 exec($cmd, $output, $val);
156 $this->assertEquals(0, $val, "Command returned error ($cmd) ($val)");
157 return implode("", $output);
160 protected function findCommand($name) {
161 $paths = explode(PATH_SEPARATOR
, getenv('PATH'));
162 foreach ($paths as $path) {
163 if (file_exists("$path/$name")) {
164 return "$path/$name";