dcd2dfddde1907353048b97649555298572623c8
[moodle.git] / mdeploytest.php
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
18 /**
19  * PHPUnit tests for the mdeploy.php utility
20  *
21  * Because the mdeploy.php can't be part of the Moodle code itself, this tests must be
22  * executed using something like:
23  *
24  *  $ phpunit --no-configuration mdeploytest
25  *
26  * @package     core
27  * @copyright   2012 David Mudrak <david@moodle.com>
28  * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
29  */
31 require(__DIR__.'/mdeploy.php');
33 /**
34  * Provides testable input options.
35  *
36  * @copyright 2012 David Mudrak <david@moodle.com>
37  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38  */
39 class input_fake_provider extends input_provider {
41     /** @var array */
42     protected $fakeoptions = array();
44     /**
45      * Sets fake raw options.
46      *
47      * @param array $options
48      */
49     public function set_fake_options(array $options) {
50         $this->fakeoptions = $options;
51         $this->populate_options();
52     }
54     /**
55      * Returns the explicitly set fake options.
56      *
57      * @return array
58      */
59     protected function parse_raw_options() {
60         return $this->fakeoptions;
61     }
62 }
64 /**
65  * Testable subclass.
66  *
67  * @copyright 2012 David Mudrak <david@moodle.com>
68  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
69  */
70 class testable_input_manager extends input_manager {
72     /**
73      * Provides access to the protected method so we can test it explicitly.
74      */
75     public function cast_value($raw, $type) {
76         return parent::cast_value($raw, $type);
77     }
79     /**
80      * Sets the fake input provider.
81      */
82     protected function initialize() {
83         $this->inputprovider = input_fake_provider::instance();
84     }
85 }
88 /**
89  * Testable subclass
90  *
91  * @copyright 2012 David Mudrak <david@moodle.com>
92  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
93  */
94 class testable_worker extends worker {
96     /**
97      * Provides access to the protected method.
98      */
99     public function move_directory($source, $target, $keepsourceroot = false) {
100         return parent::move_directory($source, $target, $keepsourceroot);
101     }
103     /**
104      * Provides access to the protected method.
105      */
106     public function remove_directory($path, $keeppathroot = false) {
107         return parent::remove_directory($path, $keeppathroot);
108     }
110     /**
111      * Provides access to the protected method.
112      */
113     public function create_directory_precheck($path) {
114         return parent::create_directory_precheck($path);
115     }
117     public function get_env($key) {
118         return parent::get_env($key);
119     }
123 /**
124  * Test cases for the mdeploy utility
125  *
126  * @copyright 2012 David Mudrak <david@moodle.com>
127  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
128  */
129 class mdeploytest extends PHPUnit_Framework_TestCase {
131     public function test_same_singletons() {
132         $a = input_manager::instance();
133         $b = input_manager::instance();
134         $this->assertSame($a, $b);
135     }
137     /**
138      * @dataProvider data_for_cast_value
139      */
140     public function test_cast_value($raw, $type, $result) {
141         $input = testable_input_manager::instance();
142         $this->assertSame($input->cast_value($raw, $type), $result);
143     }
145     public function data_for_cast_value() {
146         return array(
147             array('3', input_manager::TYPE_INT, 3),
148             array(4, input_manager::TYPE_INT, 4),
149             array('', input_manager::TYPE_INT, 0),
151             array(true, input_manager::TYPE_FLAG, true),
152             array(false, input_manager::TYPE_FLAG, true),
153             array(0, input_manager::TYPE_FLAG, true),
154             array('1', input_manager::TYPE_FLAG, true),
155             array('0', input_manager::TYPE_FLAG, true),
156             array('muhehe', input_manager::TYPE_FLAG, true),
158             array('C:\\WINDOWS\\user.dat', input_manager::TYPE_PATH, 'C:/WINDOWS/user.dat'),
159             array('D:\xampp\htdocs\24_integration/mdeploy.php', input_manager::TYPE_PATH, 'D:/xampp/htdocs/24_integration/mdeploy.php'),
160             array('d:/xampp/htdocs/24_integration/mdeploy.php', input_manager::TYPE_PATH, 'd:/xampp/htdocs/24_integration/mdeploy.php'),
161             array('../../../etc/passwd', input_manager::TYPE_PATH, '/etc/passwd'),
162             array('///////.././public_html/test.php', input_manager::TYPE_PATH, '/public_html/test.php'),
164             array("!@#$%|/etc/qwerty\n\n\t\n\r", input_manager::TYPE_RAW, "!@#$%|/etc/qwerty\n\n\t\n\r"),
166             array("\nrock'n'roll.mp3\t.exe", input_manager::TYPE_FILE, 'rocknroll.mp3.exe'),
168             array('http://localhost/moodle/dev/plugin.zip', input_manager::TYPE_URL, 'http://localhost/moodle/dev/plugin.zip'),
169             array(
170                 'https://moodle.org/plugins/download.php/1292/mod_stampcoll_moodle23_2012062201.zip',
171                 input_manager::TYPE_URL,
172                 'https://moodle.org/plugins/download.php/1292/mod_stampcoll_moodle23_2012062201.zip'
173             ),
175             array('5e8d2ea4f50d154730100b1645fbad67', input_manager::TYPE_MD5, '5e8d2ea4f50d154730100b1645fbad67'),
176         );
177     }
179     /**
180      * @expectedException invalid_option_exception
181      */
182     public function test_input_type_path_multiple_colons() {
183         $input = testable_input_manager::instance();
184         $input->cast_value('C:\apache\log:file', input_manager::TYPE_PATH); // must throw exception
185     }
187     /**
188      * @expectedException invalid_option_exception
189      */
190     public function test_input_type_path_invalid_drive_label() {
191         $input = testable_input_manager::instance();
192         $input->cast_value('0:/srv/moodledata', input_manager::TYPE_PATH); // must throw exception
193     }
195     /**
196      * @expectedException invalid_option_exception
197      */
198     public function test_input_type_path_invalid_colon() {
199         $input = testable_input_manager::instance();
200         $input->cast_value('/var/www/moodle:2.5', input_manager::TYPE_PATH); // must throw exception
201     }
203     /**
204      * @expectedException invalid_coding_exception
205      */
206     public function test_cast_array_argument() {
207         $input = testable_input_manager::instance();
208         $input->cast_value(array(1, 2, 3), input_manager::TYPE_INT); // must throw exception
209     }
211     /**
212      * @expectedException invalid_coding_exception
213      */
214     public function test_cast_object_argument() {
215         $input = testable_input_manager::instance();
216         $o = new stdClass();
217         $input->cast_value($o, input_manager::TYPE_INT); // must throw exception
218     }
220     /**
221      * @expectedException invalid_option_exception
222      */
223     public function test_cast_invalid_url_value() {
224         $input = testable_input_manager::instance();
225         $invalid = 'file:///etc/passwd';
226         $input->cast_value($invalid, input_manager::TYPE_URL); // must throw exception
227     }
229     /**
230      * @expectedException invalid_option_exception
231      */
232     public function test_cast_invalid_md5_value() {
233         $input = testable_input_manager::instance();
234         $invalid = 'this is not a valid md5 hash';
235         $input->cast_value($invalid, input_manager::TYPE_MD5); // must throw exception
236     }
238     /**
239      * @expectedException invalid_option_exception
240      */
241     public function test_cast_tilde_in_path() {
242         $input = testable_input_manager::instance();
243         $invalid = '~/public_html/moodle_dev';
244         $input->cast_value($invalid, input_manager::TYPE_PATH); // must throw exception
245     }
247     public function test_has_option() {
248         $provider = input_fake_provider::instance();
250         $provider->set_fake_options(array());
251         $this->assertFalse($provider->has_option('foo')); // foo not passed
253         $provider->set_fake_options(array('foo' => 1));
254         $this->assertFalse($provider->has_option('foo')); // foo passed but not a known option
256         $provider->set_fake_options(array('foo' => 1, 'help' => false));
257         $this->assertTrue($provider->has_option('help')); // help passed and it is a flag (value ignored)
258         $this->assertTrue($provider->has_option('h')); // 'h' is a shortname for 'help'
259     }
261     public function test_get_option() {
262         $input = testable_input_manager::instance();
263         $provider = input_fake_provider::instance();
265         $provider->set_fake_options(array('help' => false, 'passfile' => '_mdeploy.123456'));
266         $this->assertTrue($input->get_option('h'));
267         $this->assertEquals($input->get_option('passfile'), '_mdeploy.123456');
268         $this->assertEquals($input->get_option('password', 'admin123'), 'admin123');
269         try {
270             $this->assertEquals($input->get_option('password'), 'admin123'); // must throw exception (not passed but required)
271             $this->assertTrue(false);
272         } catch (missing_option_exception $e) {
273             $this->assertTrue(true);
274         }
275     }
277     public function test_moving_and_removing_directories() {
278         $worker = testable_worker::instance();
280         $root = sys_get_temp_dir().'/'.uniqid('mdeploytest', true);
281         mkdir($root.'/a', 0777, true);
282         touch($root.'/a/a.txt');
284         $this->assertTrue(file_exists($root.'/a/a.txt'));
285         $this->assertFalse(file_exists($root.'/b/a.txt'));
286         $this->assertTrue($worker->move_directory($root.'/a', $root.'/b'));
287         $this->assertFalse(is_dir($root.'/a'));
288         $this->assertTrue(file_exists($root.'/b/a.txt'));
289         $this->assertTrue($worker->move_directory($root.'/b', $root.'/c', true));
290         $this->assertTrue(file_exists($root.'/c/a.txt'));
291         $this->assertFalse(file_exists($root.'/b/a.txt'));
292         $this->assertTrue(is_dir($root.'/b'));
293         $this->assertTrue($worker->remove_directory($root.'/c', true));
294         $this->assertFalse(file_exists($root.'/c/a.txt'));
295         $this->assertTrue($worker->remove_directory($root.'/c'));
296         $this->assertFalse(is_dir($root.'/c'));
297     }
299     public function test_create_directory_precheck() {
300         $worker = testable_worker::instance();
302         $root = sys_get_temp_dir().'/'.uniqid('mdeploytest', true);
303         $this->assertFalse(file_exists($root));
304         $this->assertTrue($worker->create_directory_precheck($root));
305         $this->assertFalse(file_exists($root)); // The precheck is supposed to remove it again.
306     }
308     /**
309      * Test that an invalid setting throws an exception.
310      *
311      * @dataProvider get_env_unlisted_provider
312      * @expectedException invalid_setting_exception
313      * @expectedExceptionMessageRegExp /^Requested environment setting '[^']*' is invalid.$/
314      */
315     public function test_get_env_unlisted($key) {
316         $worker = testable_worker::instance();
317         $worker->get_env($key);
318     }
320     public function get_env_unlisted_provider() {
321         return array(
322             // Completely invalid environment variables.
323             array('example'),
324             array('invalid'),
326             // Valid ones which have not been whitelisted.
327             array('noemailever'),
328             array('dbname'),
329         );
330     }
332     /**
333      * Test that a valid, but unset setting throws an exception.
334      *
335      * @dataProvider get_env_valid_provider
336      * @expectedException invalid_setting_exception
337      * @expectedExceptionMessageRegExp /^Requested environment setting '[^']*' is not current set.$/
338      */
339     public function test_get_env_unset($key) {
340         // Ensure that the setting is currently unset.
341         global $CFG;
342         $CFG->$key = null;
344         $worker = testable_worker::instance();
345         $worker->get_env($key);
346     }
348     /**
349      * Test that a valid setting with data returns that data.
350      *
351      * @dataProvider get_env_valid_provider
352      */
353     public function test_get_env_valid($key) {
354         // Ensure that the setting is currently unset.
355         global $CFG;
356         $CFG->$key = rand(0, 1000);
358         $worker = testable_worker::instance();
359         $value = $worker->get_env($key);
361         $this->assertEquals($CFG->$key, $value);
362     }
364     public function get_env_valid_provider() {
365         return array(
366             array('dataroot'),
367             array('dirroot'),
368         );
369     }