LoggerTest.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <?php
  2. /**
  3. * Copyright (c) 2014 Thomas Müller <thomas.mueller@tmit.eu>
  4. * This file is licensed under the Affero General Public License version 3 or
  5. * later.
  6. * See the COPYING-README file.
  7. */
  8. namespace Test;
  9. use OC\Log;
  10. class LoggerTest extends TestCase {
  11. /** @var \OC\SystemConfig|\PHPUnit_Framework_MockObject_MockObject */
  12. private $config;
  13. /** @var \OCP\Support\CrashReport\IRegistry|\PHPUnit_Framework_MockObject_MockObject */
  14. private $registry;
  15. /** @var \OCP\ILogger */
  16. private $logger;
  17. /** @var array */
  18. static private $logs = array();
  19. protected function setUp() {
  20. parent::setUp();
  21. self::$logs = array();
  22. $this->config = $this->createMock(\OC\SystemConfig::class);
  23. $this->registry = $this->createMock(\OCP\Support\CrashReport\IRegistry::class);
  24. $this->logger = new Log('Test\LoggerTest', $this->config, null, $this->registry);
  25. }
  26. public function testInterpolation() {
  27. $logger = $this->logger;
  28. $logger->warning('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
  29. $expected = array('2 {Message {nothing} Bob Bar a}');
  30. $this->assertEquals($expected, $this->getLogs());
  31. }
  32. public function testAppCondition() {
  33. $this->config->expects($this->any())
  34. ->method('getValue')
  35. ->will(($this->returnValueMap([
  36. ['loglevel', \OCP\Util::WARN, \OCP\Util::WARN],
  37. ['log.condition', [], ['apps' => ['files']]]
  38. ])));
  39. $logger = $this->logger;
  40. $logger->info('Don\'t display info messages');
  41. $logger->info('Show info messages of files app', ['app' => 'files']);
  42. $logger->warning('Show warning messages of other apps');
  43. $expected = [
  44. '1 Show info messages of files app',
  45. '2 Show warning messages of other apps',
  46. ];
  47. $this->assertEquals($expected, $this->getLogs());
  48. }
  49. private function getLogs() {
  50. return self::$logs;
  51. }
  52. public static function write($app, $message, $level) {
  53. self::$logs[]= "$level $message";
  54. }
  55. public function userAndPasswordData() {
  56. return [
  57. ['abc', 'def'],
  58. ['mySpecialUsername', 'MySuperSecretPassword'],
  59. ['my-user', '324324()#ä234'],
  60. ['my-user', ')qwer'],
  61. ['my-user', 'qwer)asdf'],
  62. ['my-user', 'qwer)'],
  63. ['my-user', '(qwer'],
  64. ['my-user', 'qwer(asdf'],
  65. ['my-user', 'qwer('],
  66. ];
  67. }
  68. /**
  69. * @dataProvider userAndPasswordData
  70. */
  71. public function testDetectlogin($user, $password) {
  72. $e = new \Exception('test');
  73. $this->registry->expects($this->once())
  74. ->method('delegateReport')
  75. ->with($e, ['level' => 3]);
  76. $this->logger->logException($e);
  77. $logLines = $this->getLogs();
  78. foreach($logLines as $logLine) {
  79. $this->assertNotContains($user, $logLine);
  80. $this->assertNotContains($password, $logLine);
  81. $this->assertContains('login(*** sensitive parameters replaced ***)', $logLine);
  82. }
  83. }
  84. /**
  85. * @dataProvider userAndPasswordData
  86. */
  87. public function testDetectcheckPassword($user, $password) {
  88. $e = new \Exception('test');
  89. $this->registry->expects($this->once())
  90. ->method('delegateReport')
  91. ->with($e, ['level' => 3]);
  92. $this->logger->logException($e);
  93. $logLines = $this->getLogs();
  94. foreach($logLines as $logLine) {
  95. $this->assertNotContains($user, $logLine);
  96. $this->assertNotContains($password, $logLine);
  97. $this->assertContains('checkPassword(*** sensitive parameters replaced ***)', $logLine);
  98. }
  99. }
  100. /**
  101. * @dataProvider userAndPasswordData
  102. */
  103. public function testDetectvalidateUserPass($user, $password) {
  104. $e = new \Exception('test');
  105. $this->registry->expects($this->once())
  106. ->method('delegateReport')
  107. ->with($e, ['level' => 3]);
  108. $this->logger->logException($e);
  109. $logLines = $this->getLogs();
  110. foreach($logLines as $logLine) {
  111. $this->assertNotContains($user, $logLine);
  112. $this->assertNotContains($password, $logLine);
  113. $this->assertContains('validateUserPass(*** sensitive parameters replaced ***)', $logLine);
  114. }
  115. }
  116. /**
  117. * @dataProvider userAndPasswordData
  118. */
  119. public function testDetecttryLogin($user, $password) {
  120. $e = new \Exception('test');
  121. $this->registry->expects($this->once())
  122. ->method('delegateReport')
  123. ->with($e, ['level' => 3]);
  124. $this->logger->logException($e);
  125. $logLines = $this->getLogs();
  126. foreach($logLines as $logLine) {
  127. $this->assertNotContains($user, $logLine);
  128. $this->assertNotContains($password, $logLine);
  129. $this->assertContains('tryLogin(*** sensitive parameters replaced ***)', $logLine);
  130. }
  131. }
  132. /**
  133. * @dataProvider userAndPasswordData
  134. */
  135. public function testDetectclosure($user, $password) {
  136. $a = function($user, $password) {
  137. throw new \Exception('test');
  138. };
  139. $this->registry->expects($this->once())
  140. ->method('delegateReport');
  141. try {
  142. $a($user, $password);
  143. } catch (\Exception $e) {
  144. $this->logger->logException($e);
  145. }
  146. $logLines = $this->getLogs();
  147. foreach($logLines as $logLine) {
  148. $log = explode('\n', $logLine);
  149. unset($log[1]); // Remove `testDetectclosure(` because we are not testing this here, but the closure on stack trace 0
  150. $logLine = implode('\n', $log);
  151. $this->assertNotContains($user, $logLine);
  152. $this->assertNotContains($password, $logLine);
  153. $this->assertContains('{closure}(*** sensitive parameters replaced ***)', $logLine);
  154. }
  155. }
  156. public function dataGetLogClass() {
  157. return [
  158. ['file', \OC\Log\File::class],
  159. ['errorlog', \OC\Log\Errorlog::class],
  160. ['syslog', \OC\Log\Syslog::class],
  161. ['owncloud', \OC\Log\File::class],
  162. ['nextcloud', \OC\Log\File::class],
  163. ['foobar', \OC\Log\File::class],
  164. ];
  165. }
  166. /**
  167. * @dataProvider dataGetLogClass
  168. */
  169. public function testGetLogClass($type, $class) {
  170. $this->assertEquals($class, Log::getLogClass($type));
  171. }
  172. }