TestFileLogHandler.kt 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * Nextcloud Android client application
  3. *
  4. * @author Chris Narkiewicz
  5. * Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Affero General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. package com.nextcloud.client.logger
  21. import java.io.File
  22. import java.nio.charset.Charset
  23. import java.nio.file.Files
  24. import org.junit.Assert.assertEquals
  25. import org.junit.Assert.assertFalse
  26. import org.junit.Assert.assertTrue
  27. import org.junit.Before
  28. import org.junit.Test
  29. class TestFileLogHandler {
  30. private lateinit var logDir: File
  31. private fun readLogFile(name: String): String {
  32. val logFile = File(logDir, name)
  33. val raw = Files.readAllBytes(logFile.toPath())
  34. return String(raw, Charset.forName("UTF-8"))
  35. }
  36. private fun writeLogFile(name: String, content: String) {
  37. val logFile = File(logDir, name)
  38. Files.write(logFile.toPath(), content.toByteArray(Charsets.UTF_8))
  39. }
  40. @Before
  41. fun setUp() {
  42. logDir = Files.createTempDirectory("logger-test-").toFile()
  43. }
  44. @Test
  45. fun `logs dir is created on open`() {
  46. // GIVEN
  47. // logs directory does not exist
  48. val nonexistingLogsDir = File(logDir, "subdir")
  49. assertFalse(nonexistingLogsDir.exists())
  50. // WHEN
  51. // file is opened
  52. val handler = FileLogHandler(nonexistingLogsDir, "log.txt", 1000)
  53. handler.open()
  54. // THEN
  55. // directory is created
  56. assertTrue(nonexistingLogsDir.exists())
  57. }
  58. @Test
  59. fun `log test helpers`() {
  60. val filename = "test.txt"
  61. val expected = "Hello, world!"
  62. writeLogFile(filename, expected)
  63. val readBack = readLogFile(filename)
  64. assertEquals(expected, readBack)
  65. }
  66. @Test
  67. fun `rotate files`() {
  68. // GIVEN
  69. // log contains files
  70. writeLogFile("log.txt", "0")
  71. writeLogFile("log.txt.0", "1")
  72. writeLogFile("log.txt.1", "2")
  73. writeLogFile("log.txt.2", "3")
  74. val writer = FileLogHandler(logDir, "log.txt", 1024)
  75. // WHEN
  76. // files are rotated
  77. writer.rotateLogs()
  78. // THEN
  79. // last file is removed
  80. // all remaining files are advanced by 1 step
  81. assertFalse(File(logDir, "log.txt").exists())
  82. assertEquals("0", readLogFile("log.txt.0"))
  83. assertEquals("1", readLogFile("log.txt.1"))
  84. assertEquals("2", readLogFile("log.txt.2"))
  85. }
  86. @Test
  87. fun `log file is rotated when crossed max size`() {
  88. // GIVEN
  89. // log file contains 10 bytes
  90. // log file limit is 20 bytes
  91. // log writer is opened
  92. writeLogFile("log.txt", "0123456789")
  93. val writer = FileLogHandler(logDir, "log.txt", 20)
  94. writer.open()
  95. // WHEN
  96. // writing 2nd log entry of 11 bytes
  97. writer.write("0123456789!") // 11 bytes
  98. // THEN
  99. // log file is closed and rotated
  100. val rotatedContent = readLogFile("log.txt.0")
  101. assertEquals("01234567890123456789!", rotatedContent)
  102. }
  103. @Test
  104. fun `log file is reopened after rotation`() {
  105. // GIVEN
  106. // log file contains 10 bytes
  107. // log file limit is 20 bytes
  108. // log writer is opened
  109. writeLogFile("log.txt", "0123456789")
  110. val writer = FileLogHandler(logDir, "log.txt", 20)
  111. writer.open()
  112. // WHEN
  113. // writing 2nd log entry of 11 bytes
  114. // writing another log entry
  115. // closing log
  116. writer.write("0123456789!") // 11 bytes
  117. writer.write("Hello!")
  118. writer.close()
  119. // THEN
  120. // current log contains last entry
  121. val lastEntry = readLogFile("log.txt")
  122. assertEquals("Hello!", lastEntry)
  123. }
  124. @Test
  125. fun `load log lines from files`() {
  126. // GIVEN
  127. // multiple log files exist
  128. // log files have lines
  129. writeLogFile("log.txt.2", "line1\nline2\nline3")
  130. writeLogFile("log.txt.1", "line4\nline5\nline6")
  131. writeLogFile("log.txt.0", "line7\nline8\nline9")
  132. writeLogFile("log.txt", "line10\nline11\nline12")
  133. // WHEN
  134. // log file is read including rotated content
  135. val writer = FileLogHandler(logDir, "log.txt", 1000)
  136. val lines = writer.loadLogFiles(3)
  137. // THEN
  138. // all files are loaded
  139. // lines are loaded in correct order
  140. assertEquals(12, lines.size)
  141. assertEquals(
  142. listOf(
  143. "line1", "line2", "line3",
  144. "line4", "line5", "line6",
  145. "line7", "line8", "line9",
  146. "line10", "line11", "line12"
  147. ),
  148. lines
  149. )
  150. }
  151. @Test
  152. fun `load log lines from files with gaps between rotated files`() {
  153. // GIVEN
  154. // multiple log files exist
  155. // log files have lines
  156. // some rotated files are deleted
  157. writeLogFile("log.txt", "line1\nline2\nline3")
  158. writeLogFile("log.txt.2", "line4\nline5\nline6")
  159. // WHEN
  160. // log file is read including rotated content
  161. val writer = FileLogHandler(logDir, "log.txt", 1000)
  162. val lines = writer.loadLogFiles(3)
  163. // THEN
  164. // all files are loaded
  165. assertEquals(6, lines.size)
  166. }
  167. @Test(expected = IllegalArgumentException::class)
  168. fun `load log lines - negative count is illegal`() {
  169. // WHEN
  170. // requesting negative number of rotated files
  171. val writer = FileLogHandler(logDir, "log.txt", 1000)
  172. val lines = writer.loadLogFiles(-1)
  173. // THEN
  174. // illegal argument exception
  175. }
  176. @Test
  177. fun `all log files are deleted`() {
  178. // GIVEN
  179. // log files exist
  180. val handler = FileLogHandler(logDir, "log.txt", 100)
  181. for (i in 0 until handler.maxLogFilesCount) {
  182. handler.rotateLogs()
  183. handler.open()
  184. handler.write("new log entry")
  185. handler.close()
  186. }
  187. assertEquals(handler.maxLogFilesCount, logDir.listFiles().size)
  188. // WHEN
  189. // files are deleted
  190. handler.deleteAll()
  191. // THEN
  192. // all files are deleted
  193. assertEquals(0, logDir.listFiles().size)
  194. }
  195. }