PageRenderTime 33ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/backup/util/loggers/tests/logger_test.php

https://bitbucket.org/kudutest1/moodlegit
PHP | 392 lines | 262 code | 41 blank | 89 comment | 6 complexity | 54bd44f6bdc6b137c077f7192cdc5139 MD5 | raw file
  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * @package core_backup
  18. * @category phpunit
  19. * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
  20. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  21. */
  22. defined('MOODLE_INTERNAL') || die();
  23. // Include all the needed stuff
  24. global $CFG;
  25. require_once($CFG->dirroot . '/backup/util/interfaces/checksumable.class.php');
  26. require_once($CFG->dirroot . '/backup/backup.class.php');
  27. require_once($CFG->dirroot . '/backup/util/loggers/base_logger.class.php');
  28. require_once($CFG->dirroot . '/backup/util/loggers/error_log_logger.class.php');
  29. require_once($CFG->dirroot . '/backup/util/loggers/output_text_logger.class.php');
  30. require_once($CFG->dirroot . '/backup/util/loggers/output_indented_logger.class.php');
  31. require_once($CFG->dirroot . '/backup/util/loggers/database_logger.class.php');
  32. require_once($CFG->dirroot . '/backup/util/loggers/file_logger.class.php');
  33. /**
  34. * logger tests (all)
  35. */
  36. class backup_logger_testcase extends basic_testcase {
  37. /**
  38. * test base_logger class
  39. */
  40. function test_base_logger() {
  41. // Test logger with simple action (message * level)
  42. $lo = new mock_base_logger1(backup::LOG_ERROR);
  43. $msg = 13;
  44. $this->assertEquals($lo->process($msg, backup::LOG_ERROR), $msg * backup::LOG_ERROR);
  45. // With lowest level must return true
  46. $lo = new mock_base_logger1(backup::LOG_ERROR);
  47. $msg = 13;
  48. $this->assertTrue($lo->process($msg, backup::LOG_DEBUG));
  49. // Chain 2 loggers, we must get as result the result of the inner one
  50. $lo1 = new mock_base_logger1(backup::LOG_ERROR);
  51. $lo2 = new mock_base_logger2(backup::LOG_ERROR);
  52. $lo1->set_next($lo2);
  53. $msg = 13;
  54. $this->assertEquals($lo1->process($msg, backup::LOG_ERROR), $msg + backup::LOG_ERROR);
  55. // Try circular reference
  56. $lo1 = new mock_base_logger1(backup::LOG_ERROR);
  57. try {
  58. $lo1->set_next($lo1); //self
  59. $this->assertTrue(false, 'base_logger_exception expected');
  60. } catch (exception $e) {
  61. $this->assertTrue($e instanceof base_logger_exception);
  62. $this->assertEquals($e->errorcode, 'logger_circular_reference');
  63. $this->assertTrue($e->a instanceof stdclass);
  64. $this->assertEquals($e->a->main, get_class($lo1));
  65. $this->assertEquals($e->a->alreadyinchain, get_class($lo1));
  66. }
  67. $lo1 = new mock_base_logger1(backup::LOG_ERROR);
  68. $lo2 = new mock_base_logger2(backup::LOG_ERROR);
  69. $lo3 = new mock_base_logger3(backup::LOG_ERROR);
  70. $lo1->set_next($lo2);
  71. $lo2->set_next($lo3);
  72. try {
  73. $lo3->set_next($lo1);
  74. $this->assertTrue(false, 'base_logger_exception expected');
  75. } catch (exception $e) {
  76. $this->assertTrue($e instanceof base_logger_exception);
  77. $this->assertEquals($e->errorcode, 'logger_circular_reference');
  78. $this->assertTrue($e->a instanceof stdclass);
  79. $this->assertEquals($e->a->main, get_class($lo1));
  80. $this->assertEquals($e->a->alreadyinchain, get_class($lo3));
  81. }
  82. // Test stopper logger
  83. $lo1 = new mock_base_logger1(backup::LOG_ERROR);
  84. $lo2 = new mock_base_logger2(backup::LOG_ERROR);
  85. $lo3 = new mock_base_logger3(backup::LOG_ERROR);
  86. $lo1->set_next($lo2);
  87. $lo2->set_next($lo3);
  88. $this->assertFalse($lo1->process('test', backup::LOG_ERROR));
  89. // Test checksum correct
  90. $lo1 = new mock_base_logger1(backup::LOG_ERROR);
  91. $lo1->is_checksum_correct(get_class($lo1) . '-' . backup::LOG_ERROR);
  92. // Test get_levelstr()
  93. $lo1 = new mock_base_logger1(backup::LOG_ERROR);
  94. $this->assertEquals($lo1->get_levelstr(backup::LOG_NONE), 'undefined');
  95. $this->assertEquals($lo1->get_levelstr(backup::LOG_ERROR), 'error');
  96. $this->assertEquals($lo1->get_levelstr(backup::LOG_WARNING), 'warn');
  97. $this->assertEquals($lo1->get_levelstr(backup::LOG_INFO), 'info');
  98. $this->assertEquals($lo1->get_levelstr(backup::LOG_DEBUG), 'debug');
  99. }
  100. /**
  101. * test error_log_logger class
  102. */
  103. function test_error_log_logger() {
  104. // Not much really to test, just instantiate and execute, should return true
  105. $lo = new error_log_logger(backup::LOG_ERROR);
  106. $this->assertTrue($lo instanceof error_log_logger);
  107. $message = 'This log exists because you have run Moodle unit tests: Ignore it';
  108. $result = $lo->process($message, backup::LOG_ERROR);
  109. $this->assertTrue($result);
  110. }
  111. /**
  112. * test output_text_logger class
  113. */
  114. function test_output_text_logger() {
  115. // Instantiate without date nor level output
  116. $lo = new output_text_logger(backup::LOG_ERROR);
  117. $this->assertTrue($lo instanceof output_text_logger);
  118. $message = 'testing output_text_logger';
  119. ob_start(); // Capture output
  120. $result = $lo->process($message, backup::LOG_ERROR);
  121. $contents = ob_get_contents();
  122. ob_end_clean(); // End capture and discard
  123. $this->assertTrue($result);
  124. $this->assertTrue(strpos($contents, $message) !== false);
  125. // Instantiate with date and level output
  126. $lo = new output_text_logger(backup::LOG_ERROR, true, true);
  127. $this->assertTrue($lo instanceof output_text_logger);
  128. $message = 'testing output_text_logger';
  129. ob_start(); // Capture output
  130. $result = $lo->process($message, backup::LOG_ERROR);
  131. $contents = ob_get_contents();
  132. ob_end_clean(); // End capture and discard
  133. $this->assertTrue($result);
  134. $this->assertTrue(strpos($contents,'[') === 0);
  135. $this->assertTrue(strpos($contents,'[error]') !== false);
  136. $this->assertTrue(strpos($contents, $message) !== false);
  137. $this->assertTrue(substr_count($contents , '] ') >= 2);
  138. }
  139. /**
  140. * test output_indented_logger class
  141. */
  142. function test_output_indented_logger() {
  143. // Instantiate without date nor level output
  144. $options = array('depth' => 2);
  145. $lo = new output_indented_logger(backup::LOG_ERROR);
  146. $this->assertTrue($lo instanceof output_indented_logger);
  147. $message = 'testing output_indented_logger';
  148. ob_start(); // Capture output
  149. $result = $lo->process($message, backup::LOG_ERROR, $options);
  150. $contents = ob_get_contents();
  151. ob_end_clean(); // End capture and discard
  152. $this->assertTrue($result);
  153. if (defined('STDOUT')) {
  154. $check = ' ';
  155. } else {
  156. $check = '&nbsp;&nbsp;';
  157. }
  158. $this->assertTrue(strpos($contents, str_repeat($check, $options['depth']) . $message) !== false);
  159. // Instantiate with date and level output
  160. $options = array('depth' => 3);
  161. $lo = new output_indented_logger(backup::LOG_ERROR, true, true);
  162. $this->assertTrue($lo instanceof output_indented_logger);
  163. $message = 'testing output_indented_logger';
  164. ob_start(); // Capture output
  165. $result = $lo->process($message, backup::LOG_ERROR, $options);
  166. $contents = ob_get_contents();
  167. ob_end_clean(); // End capture and discard
  168. $this->assertTrue($result);
  169. $this->assertTrue(strpos($contents,'[') === 0);
  170. $this->assertTrue(strpos($contents,'[error]') !== false);
  171. $this->assertTrue(strpos($contents, $message) !== false);
  172. $this->assertTrue(substr_count($contents , '] ') >= 2);
  173. if (defined('STDOUT')) {
  174. $check = ' ';
  175. } else {
  176. $check = '&nbsp;&nbsp;';
  177. }
  178. $this->assertTrue(strpos($contents, str_repeat($check, $options['depth']) . $message) !== false);
  179. }
  180. /**
  181. * test database_logger class
  182. */
  183. function test_database_logger() {
  184. // Instantiate with date and level output (and with specs from the global moodle "log" table so checks will pass
  185. $now = time();
  186. $datecol = 'time';
  187. $levelcol = 'action';
  188. $messagecol = 'info';
  189. $logtable = 'log';
  190. $columns = array('url' => 'http://127.0.0.1');
  191. $loglevel = backup::LOG_ERROR;
  192. $lo = new mock_database_logger(backup::LOG_ERROR, $datecol, $levelcol, $messagecol, $logtable, $columns);
  193. $this->assertTrue($lo instanceof database_logger);
  194. $message = 'testing database_logger';
  195. $result = $lo->process($message, $loglevel);
  196. // Check everything is ready to be inserted to DB
  197. $this->assertEquals($result['table'], $logtable);
  198. $this->assertTrue($result['columns'][$datecol] >= $now);
  199. $this->assertEquals($result['columns'][$levelcol], $loglevel);
  200. $this->assertEquals($result['columns'][$messagecol], $message);
  201. $this->assertEquals($result['columns']['url'], $columns['url']);
  202. }
  203. /**
  204. * test file_logger class
  205. */
  206. function test_file_logger() {
  207. global $CFG;
  208. $file = $CFG->tempdir . '/test/test_file_logger.txt';
  209. // Remove the test dir and any content
  210. @remove_dir(dirname($file));
  211. // Recreate test dir
  212. if (!check_dir_exists(dirname($file), true, true)) {
  213. throw new moodle_exception('error_creating_temp_dir', 'error', dirname($file));
  214. }
  215. // Instantiate with date and level output, and also use the depth option
  216. $options = array('depth' => 3);
  217. $lo1 = new file_logger(backup::LOG_ERROR, true, true, $file);
  218. $this->assertTrue($lo1 instanceof file_logger);
  219. $message1 = 'testing file_logger';
  220. $result = $lo1->process($message1, backup::LOG_ERROR, $options);
  221. $this->assertTrue($result);
  222. // Another file_logger is going towrite there too without closing
  223. $options = array();
  224. $lo2 = new file_logger(backup::LOG_WARNING, true, true, $file);
  225. $this->assertTrue($lo2 instanceof file_logger);
  226. $message2 = 'testing file_logger2';
  227. $result = $lo2->process($message2, backup::LOG_WARNING, $options);
  228. $this->assertTrue($result);
  229. // Destruct loggers
  230. $lo1 = null;
  231. $lo2 = null;
  232. // Load file results to analyze them
  233. $fcontents = file_get_contents($file);
  234. $acontents = explode(PHP_EOL, $fcontents); // Split by line
  235. $this->assertTrue(strpos($acontents[0], $message1) !== false);
  236. $this->assertTrue(strpos($acontents[0], '[error]') !== false);
  237. $this->assertTrue(strpos($acontents[0], ' ') !== false);
  238. $this->assertTrue(substr_count($acontents[0] , '] ') >= 2);
  239. $this->assertTrue(strpos($acontents[1], $message2) !== false);
  240. $this->assertTrue(strpos($acontents[1], '[warn]') !== false);
  241. $this->assertTrue(strpos($acontents[1], ' ') === false);
  242. $this->assertTrue(substr_count($acontents[1] , '] ') >= 2);
  243. unlink($file); // delete file
  244. // Try one html file
  245. check_dir_exists($CFG->tempdir . '/test');
  246. $file = $CFG->tempdir . '/test/test_file_logger.html';
  247. $options = array('depth' => 1);
  248. $lo = new file_logger(backup::LOG_ERROR, true, true, $file);
  249. $this->assertTrue($lo instanceof file_logger);
  250. $this->assertTrue(file_exists($file));
  251. $message = 'testing file_logger';
  252. $result = $lo->process($message, backup::LOG_ERROR, $options);
  253. // Get file contents and inspect them
  254. $fcontents = file_get_contents($file);
  255. $this->assertTrue($result);
  256. $this->assertTrue(strpos($fcontents, $message) !== false);
  257. $this->assertTrue(strpos($fcontents, '[error]') !== false);
  258. $this->assertTrue(strpos($fcontents, '&nbsp;&nbsp;') !== false);
  259. $this->assertTrue(substr_count($fcontents , '] ') >= 2);
  260. $lo->__destruct(); // closes file handle
  261. unlink($file); // delete file
  262. // Instantiate, write something, force deletion, try to write again
  263. check_dir_exists($CFG->tempdir . '/test');
  264. $file = $CFG->tempdir . '/test/test_file_logger.html';
  265. $lo = new mock_file_logger(backup::LOG_ERROR, true, true, $file);
  266. $this->assertTrue(file_exists($file));
  267. $message = 'testing file_logger';
  268. $result = $lo->process($message, backup::LOG_ERROR);
  269. fclose($lo->get_fhandle()); // close file
  270. try {
  271. $result = @$lo->process($message, backup::LOG_ERROR); // Try to write again
  272. $this->assertTrue(false, 'base_logger_exception expected');
  273. } catch (exception $e) {
  274. $this->assertTrue($e instanceof base_logger_exception);
  275. $this->assertEquals($e->errorcode, 'error_writing_file');
  276. }
  277. // Instantiate without file
  278. try {
  279. $lo = new file_logger(backup::LOG_WARNING, true, true, '');
  280. $this->assertTrue(false, 'base_logger_exception expected');
  281. } catch (exception $e) {
  282. $this->assertTrue($e instanceof base_logger_exception);
  283. $this->assertEquals($e->errorcode, 'missing_fullpath_parameter');
  284. }
  285. // Instantiate in (near) impossible path
  286. $file = $CFG->tempdir . '/test_azby/test_file_logger.txt';
  287. try {
  288. $lo = new file_logger(backup::LOG_WARNING, true, true, $file);
  289. $this->assertTrue(false, 'base_logger_exception expected');
  290. } catch (exception $e) {
  291. $this->assertTrue($e instanceof base_logger_exception);
  292. $this->assertEquals($e->errorcode, 'file_not_writable');
  293. $this->assertEquals($e->a, $file);
  294. }
  295. // Instantiate one file logger with level = backup::LOG_NONE
  296. $file = $CFG->tempdir . '/test/test_file_logger.txt';
  297. $lo = new file_logger(backup::LOG_NONE, true, true, $file);
  298. $this->assertTrue($lo instanceof file_logger);
  299. $this->assertFalse(file_exists($file));
  300. // Remove the test dir and any content
  301. @remove_dir(dirname($file));
  302. }
  303. }
  304. /**
  305. * helper extended base_logger class that implements some methods for testing
  306. * Simply return the product of message and level
  307. */
  308. class mock_base_logger1 extends base_logger {
  309. protected function action($message, $level, $options = null) {
  310. return $message * $level; // Simply return that, for testing
  311. }
  312. public function get_levelstr($level) {
  313. return parent::get_levelstr($level);
  314. }
  315. }
  316. /**
  317. * helper extended base_logger class that implements some methods for testing
  318. * Simply return the sum of message and level
  319. */
  320. class mock_base_logger2 extends base_logger {
  321. protected function action($message, $level, $options = null) {
  322. return $message + $level; // Simply return that, for testing
  323. }
  324. }
  325. /**
  326. * helper extended base_logger class that implements some methods for testing
  327. * Simply return 8
  328. */
  329. class mock_base_logger3 extends base_logger {
  330. protected function action($message, $level, $options = null) {
  331. return false; // Simply return false, for testing stopper
  332. }
  333. }
  334. /**
  335. * helper extended database_logger class that implements some methods for testing
  336. * Returns the complete info that normally will be used by insert record calls
  337. */
  338. class mock_database_logger extends database_logger {
  339. protected function insert_log_record($table, $columns) {
  340. return array('table' => $table, 'columns' => $columns);
  341. }
  342. }
  343. /**
  344. * helper extended file_logger class that implements some methods for testing
  345. * Returns the, usually protected, handle
  346. */
  347. class mock_file_logger extends file_logger {
  348. function get_fhandle() {
  349. return $this->fhandle;
  350. }
  351. }