Skip to content

Commit 9f7c171

Browse files
committed
Tests, KDoc
1 parent e4d0be7 commit 9f7c171

File tree

8 files changed

+100
-13
lines changed

8 files changed

+100
-13
lines changed

app/src/main/kotlin/at/bitfire/davdroid/App.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,18 @@ import kotlinx.coroutines.Dispatchers
1919
import kotlinx.coroutines.GlobalScope
2020
import kotlinx.coroutines.launch
2121
import java.util.logging.Level
22+
import java.util.logging.Logger
2223
import javax.inject.Inject
2324
import kotlin.system.exitProcess
2425

2526
@HiltAndroidApp
2627
class App: Application(), Thread.UncaughtExceptionHandler, Configuration.Provider {
2728

2829
@Inject
29-
lateinit var logger: java.util.logging.Logger
30+
lateinit var logger: Logger
3031

3132
/**
32-
* Creates the LogManager singleton and thus initializes logging.
33+
* Creates the [LogManager] singleton and thus initializes logging.
3334
*/
3435
@Inject
3536
lateinit var logManager: LogManager

app/src/main/kotlin/at/bitfire/davdroid/log/LogFileHandler.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import java.util.logging.LogRecord
2525
import java.util.logging.Logger
2626

2727
/**
28-
* Logging handler to log to a verbose log file.
28+
* Logging handler that logs to a debug log file.
2929
*
3030
* Shows a permanent notification as long as it's active (until [close] is called).
3131
*

app/src/main/kotlin/at/bitfire/davdroid/log/LogManager.kt

+13
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,21 @@ import javax.inject.Singleton
2424
* Handles logging configuration and which loggers are active at a moment.
2525
* To initialize, just make sure that the [LogManager] singleton is created.
2626
*
27+
* Configures the root logger like this:
28+
*
2729
* - Always logs to logcat.
2830
* - Watches the "log to file" preference and activates or deactivates file logging accordingly.
31+
* - If "log to file" is enabled, log level is set to [Level.ALL].
32+
* - Otherwise, log level is set to [Level.INFO].
33+
*
34+
* Preferred ways to get a [Logger] are:
35+
*
36+
* - `@Inject` [Logger] for a general-purpose logger when injection is possible
37+
* - `Logger.getGlobal()` for a general-purpose logger
38+
* - `Logger.getLogger(javaClass.name)` for a specific logger that can be customized
39+
*
40+
* When using the global logger, the class name of the logging calls will still be logged, so there's
41+
* no need to always get a separate logger for each class (only if the class wants to customize it).
2942
*/
3043
@Singleton
3144
class LogManager @Inject constructor(

app/src/main/kotlin/at/bitfire/davdroid/log/LogcatHandler.kt

+9-2
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ package at.bitfire.davdroid.log
66

77
import android.os.Build
88
import android.util.Log
9+
import at.bitfire.davdroid.BuildConfig
910
import com.google.common.base.Ascii
1011

1112
import java.util.logging.Handler
1213
import java.util.logging.Level
1314
import java.util.logging.LogRecord
1415

1516
/**
16-
* Logging handler to log to Android logcat.
17+
* Logging handler that logs to Android logcat.
1718
*/
1819
internal class LogcatHandler: Handler() {
1920

@@ -25,7 +26,13 @@ internal class LogcatHandler: Handler() {
2526
val level = r.level.intValue()
2627
val text = formatter.format(r)
2728

28-
val className = PlainTextFormatter.shortClassName(r.sourceClassName)
29+
// get class name that calls the logger (or fall back to package name)
30+
val className = if (r.sourceClassName != null)
31+
PlainTextFormatter.shortClassName(r.sourceClassName)
32+
else
33+
BuildConfig.APPLICATION_ID
34+
35+
// truncate class name to 23 characters on Android <8, see Log documentation
2936
val tag = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
3037
Ascii.truncate(className, 23, "")
3138
else

app/src/main/kotlin/at/bitfire/davdroid/log/Logger.kt

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44

55
package at.bitfire.davdroid.log
66

7+
import java.util.logging.Logger
8+
9+
@Deprecated("Remove as soon as all usages are replaced")
710
object Logger {
811

9-
@Deprecated("Use @Inject j.u.l.Logger or j.u.l.Logger.getGlobal() instead", ReplaceWith("Logger.getGlobal()", "java.util.logging.Logger"))
10-
val log: java.util.logging.Logger = java.util.logging.Logger.getGlobal()
12+
@Deprecated("See LogManager for preferred ways to get a Logger.", ReplaceWith("java.util.logging.Logger.getGlobal()", "java.util.logging.Logger"))
13+
val log: Logger = Logger.getGlobal()
1114

1215
}

app/src/main/kotlin/at/bitfire/davdroid/log/PlainTextFormatter.kt

+5-3
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ class PlainTextFormatter private constructor(
4040
builder .append(DateFormatUtils.format(r.millis, "yyyy-MM-dd HH:mm:ss", Locale.ROOT))
4141
.append(" ").append(r.threadID).append(" ")
4242

43-
val className = shortClassName(r.sourceClassName)
44-
if (className != r.loggerName)
45-
builder.append("[").append(className).append("] ")
43+
if (r.sourceClassName != null) {
44+
val className = shortClassName(r.sourceClassName)
45+
if (className != r.loggerName)
46+
builder.append("[").append(className).append("] ")
47+
}
4648
}
4749

4850
builder.append(r.message)

app/src/main/kotlin/at/bitfire/davdroid/log/StringHandler.kt

+23-3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,19 @@ import com.google.common.base.Ascii
88
import java.util.logging.Handler
99
import java.util.logging.LogRecord
1010

11+
/**
12+
* Handler that writes log messages to a string buffer.
13+
*
14+
* @param maxSize Maximum size of the buffer. If the buffer exceeds this size, it will be truncated.
15+
*/
1116
class StringHandler(
1217
private val maxSize: Int
1318
): Handler() {
1419

20+
companion object {
21+
const val TRUNCATION_MARKER = "[...]"
22+
}
23+
1524
val builder = StringBuilder()
1625

1726
init {
@@ -22,10 +31,21 @@ class StringHandler(
2231
var text = formatter.format(record)
2332

2433
val currentSize = builder.length
25-
if (currentSize + text.length > maxSize)
26-
text = Ascii.truncate(text, maxSize - currentSize, "[...]")
34+
val sizeLeft = maxSize - currentSize
35+
36+
when {
37+
// Append the text if there is enough space
38+
sizeLeft > text.length ->
39+
builder.append(text)
40+
41+
// Truncate the text if there is not enough space
42+
sizeLeft > TRUNCATION_MARKER.length -> {
43+
text = Ascii.truncate(text, maxSize - currentSize, TRUNCATION_MARKER)
44+
builder.append(text)
45+
}
2746

28-
builder.append(text)
47+
// Do nothing if the buffer is already full
48+
}
2949
}
3050

3151
override fun flush() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
3+
*/
4+
5+
package at.bitfire.davdroid.log
6+
7+
import org.junit.Assert.assertEquals
8+
import org.junit.Assert.assertTrue
9+
import org.junit.Test
10+
import java.util.logging.Formatter
11+
import java.util.logging.Level
12+
import java.util.logging.LogRecord
13+
14+
class StringHandlerTest {
15+
16+
@Test
17+
fun test_logSomeText() {
18+
val handler = StringHandler(1000)
19+
handler.publish(LogRecord(Level.INFO, "Line 1"))
20+
handler.publish(LogRecord(Level.FINEST, "Line 2"))
21+
val str = handler.toString()
22+
assertTrue(str.contains("Line 1\n"))
23+
assertTrue(str.contains("Line 2\n"))
24+
}
25+
26+
@Test
27+
fun test_logSomeText_ExceedingMaxSize() {
28+
val handler = StringHandler(10).apply {
29+
formatter = object: Formatter() {
30+
override fun format(record: LogRecord) = record.message
31+
}
32+
}
33+
handler.publish(LogRecord(Level.INFO, "Line 1 Line 1 Line 1 Line 1 Line 1"))
34+
handler.publish(LogRecord(Level.FINEST, "Line 2"))
35+
36+
val str = handler.toString()
37+
assertEquals(10, handler.toString().length)
38+
assertEquals("Line [...]", str)
39+
}
40+
41+
}

0 commit comments

Comments
 (0)