Commit | Line | Data |
---|---|---|
62e2c027 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
4 | | CiviCRM version 5 | | |
5 | +--------------------------------------------------------------------+ | |
adc7fffe | 6 | | Copyright CiviCRM LLC (c) 2004-2020 | |
62e2c027 TO |
7 | +--------------------------------------------------------------------+ |
8 | | This file is a part of CiviCRM. | | |
9 | | | | |
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. | | |
13 | | | | |
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. | | |
18 | | | | |
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 | +--------------------------------------------------------------------+ | |
25 | */ | |
26 | ||
27 | /** | |
28 | * Check that various CLI runners are able to bootstrap an environment with | |
29 | * reasonable paths. | |
30 | * | |
31 | * This test assumes that you have built with "civibuild" (or configured cv.json) | |
32 | * to provide canonical/expected values. | |
33 | * | |
34 | * It then executes the any supported CLI tools (cv, drush, wp) and checks if | |
35 | * their output matches the expected value. | |
36 | * | |
37 | * @group e2e | |
38 | */ | |
39 | class E2E_Extern_CliRunnerTest extends CiviEndToEndTestCase { | |
40 | ||
41 | protected function setUp() { | |
42 | parent::setUp(); | |
43 | ||
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)"); | |
47 | } | |
48 | } | |
49 | } | |
50 | ||
51 | protected function tearDown() { | |
52 | parent::tearDown(); | |
53 | } | |
54 | ||
55 | /** | |
56 | * @return array | |
57 | * Each case gives a name (eg "cv") and template for executing the command | |
58 | * (eg "cv ev @PHP"). | |
59 | */ | |
60 | public function getRunners() { | |
61 | $cliRunners = []; | |
62 | ||
63 | if (CIVICRM_UF === 'WordPress') { | |
64 | $cliRunners['wp'] = ['wp', 'wp eval \'civicrm_initialize();\'@PHP']; | |
65 | } | |
66 | if (CIVICRM_UF === 'Drupal' || CIVICRM_UF === 'Backdrop') { | |
67 | $cliRunners['drush'] = ['drush', 'drush ev \'civicrm_initialize();\'@PHP']; | |
68 | } | |
69 | // TODO: Drupal8 w/drush (doesn't use civicrm_initialize?) | |
70 | ||
71 | $cliRunners['cv'] = ['cv', 'cv ev @PHP']; | |
72 | ||
73 | return $cliRunners; | |
74 | } | |
75 | ||
76 | public function getRunnersAndPaths() { | |
77 | $exs = []; | |
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']); | |
81 | } | |
82 | return $exs; | |
83 | } | |
84 | ||
85 | /** | |
86 | * @param string $name | |
87 | * The name of the command we're testing with. | |
88 | * Ex: 'cv' | |
89 | * @param string $r | |
90 | * Ex: 'cv ev @PHP' | |
91 | * @dataProvider getRunners | |
92 | */ | |
93 | public function testBasicPathUrl($name, $r) { | |
94 | $this->assertNotEmpty($this->findCommand($name), 'The command "$name" does not appear in the PATH.'); | |
95 | ||
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\')')); | |
101 | ||
102 | $ufrUrl = $this->callRunnerJson($r, 'CRM_Core_Config::singleton()->userFrameworkResourceURL'); | |
103 | $crmUrl = $this->callRunnerJson($r, 'Civi::paths()->getUrl("[civicrm.root]/.")'); | |
0d4d8d54 | 104 | $this->assertEquals(rtrim($crmUrl, '/'), rtrim($ufrUrl, '/')); |
62e2c027 TO |
105 | } |
106 | ||
107 | /** | |
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. | |
110 | * | |
111 | * @param string $name | |
112 | * The name of the command we're testing with. | |
113 | * Ex: 'cv' | |
114 | * @param string $r | |
115 | * Ex: 'cv ev @PHP' | |
116 | * @param string $fileExpr | |
117 | * Ex: '[civicrm.root]/LICENSE' | |
118 | * @dataProvider getRunnersAndPaths | |
119 | */ | |
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)" | |
129 | ); | |
130 | } | |
131 | ||
132 | /** | |
133 | * @param string $runner | |
134 | * Ex: 'cv ev @PHP' | |
135 | * @param string $phpExpr | |
136 | * PHP expression to evaluate and return. (Encoded+decoded as JSON) | |
137 | * @return mixed | |
138 | * The result of running $phpExpr through the given $runner. | |
139 | */ | |
140 | protected function callRunnerJson($runner, $phpExpr) { | |
141 | $json = $this->callRunnerOk($runner, "echo json_encode($phpExpr);"); | |
142 | return json_decode($json); | |
143 | } | |
144 | ||
145 | /** | |
146 | * @param string $runner | |
147 | * Ex: 'cv ev @PHP' | |
148 | * @param string $phpStmt | |
149 | * PHP code to execute | |
150 | * @return string | |
151 | * The console output of running $phpStmt through the given $runner. | |
152 | */ | |
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); | |
158 | } | |
159 | ||
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"; | |
165 | } | |
166 | } | |
167 | return NULL; | |
168 | } | |
169 | ||
170 | } |