blob: cb38846a0514ecfe614145d2bec9a6fda56e2007 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.dump
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.io.FakeBasicFileAttributes
import com.android.systemui.util.io.Files
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import java.io.BufferedWriter
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.io.OutputStreamWriter
import java.io.PrintWriter
import java.nio.file.LinkOption
import java.nio.file.OpenOption
import java.nio.file.Paths
import java.nio.file.attribute.BasicFileAttributes
import java.util.Arrays
@SmallTest
class LogEulogizerTest : SysuiTestCase() {
lateinit var eulogizer: LogBufferEulogizer
@Mock
lateinit var dumpManager: DumpManager
@Mock
lateinit var files: Files
private val clock = FakeSystemClock()
private val path = Paths.get("/foo/bar/baz.txt")
private val fileAttrs = FakeBasicFileAttributes()
private val fileStream = ByteArrayOutputStream()
private val fileWriter = BufferedWriter(OutputStreamWriter(fileStream))
private val dumpStream = ByteArrayOutputStream()
private val dumpWriter = PrintWriter(OutputStreamWriter(dumpStream))
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
eulogizer =
LogBufferEulogizer(dumpManager, clock, files, path, MIN_WRITE_GAP, MAX_READ_AGE)
Mockito.`when`(files.newBufferedWriter(eq(path), any(OpenOption::class.java)))
.thenReturn(fileWriter)
Mockito.`when`(
files.readAttributes(eq(path),
eq(BasicFileAttributes::class.java),
any(LinkOption::class.java))
).thenReturn(fileAttrs)
Mockito.`when`(files.lines(eq(path))).thenReturn(Arrays.stream(FAKE_LINES))
}
@Test
fun testFileIsCreated() {
// GIVEN that the log file doesn't already exist
Mockito.`when`(
files.readAttributes(eq(path),
eq(BasicFileAttributes::class.java),
any(LinkOption::class.java))
).thenThrow(IOException("File not found"))
// WHEN .record() is called
val exception = RuntimeException("Something bad happened")
assertEquals(exception, eulogizer.record(exception))
// THEN the buffers are dumped to the file
verify(dumpManager).dumpBuffers(any(PrintWriter::class.java), Mockito.anyInt())
assertTrue(fileStream.toString().isNotEmpty())
}
@Test
fun testExistingFileIsOverwritten() {
// GIVEN that the log file already exists but hasn't been modified in a while
fileAttrs.setLastModifiedTime(clock.currentTimeMillis() - MIN_WRITE_GAP - 20)
// WHEN .record() is called
val exception = RuntimeException("Something bad happened")
assertEquals(exception, eulogizer.record(exception))
// THEN the buffers are dumped to the file
verify(dumpManager).dumpBuffers(any(PrintWriter::class.java), Mockito.anyInt())
assertTrue(fileStream.toString().isNotEmpty())
}
@Test
fun testYoungFileIsNotOverwritten() {
// GIVEN that the log file has been modified recently
fileAttrs.setLastModifiedTime(clock.currentTimeMillis() - MIN_WRITE_GAP + 7)
// WHEN .record() is called
val exception = RuntimeException("Something bad happened")
assertEquals(exception, eulogizer.record(exception))
// THEN the file isn't written to
verify(dumpManager, never()).dumpBuffers(any(PrintWriter::class.java), Mockito.anyInt())
assertTrue(fileStream.toString().isEmpty())
}
@Test
fun testRecentFileIsDumped() {
// GIVEN that the log file was written to "recently"
fileAttrs.setLastModifiedTime(clock.currentTimeMillis() - MAX_READ_AGE + 7)
// WHEN we're asked to eulogize the log
eulogizer.readEulogyIfPresent(dumpWriter)
dumpWriter.close()
// THEN the log file is written to the output stream
verify(files).lines(eq(path))
assertTrue(dumpStream.toString().isNotBlank())
}
@Test
fun testOldFileIsNotDumped() {
// GIVEN that the log file was written to a long time ago
fileAttrs.setLastModifiedTime(clock.currentTimeMillis() - MAX_READ_AGE - 7)
// WHEN we're asked to eulogize the log
eulogizer.readEulogyIfPresent(dumpWriter)
dumpWriter.close()
// THEN the log file is NOT written to the output stream
verify(files, never()).lines(eq(path))
assertTrue(dumpStream.toString().isEmpty())
}
}
private const val MIN_WRITE_GAP = 10L
private const val MAX_READ_AGE = 100L
private val FAKE_LINES =
arrayOf(
"First line",
"Second line",
"Third line"
)