feat(logging): stragglers -> AppLog (#330)

Migrate RestartActivity's one raw Log.w site to AppLog, clearing the
final raw android.util.Log site outside the auth/lock, DB/keystore,
connectivity/send, and sync-engine migration areas so the codebase is
ready for the detekt android.util.Log guard (#331).

RestartActivity runs in the separate :restart trampoline process,
where LibreMailApplication.onCreate returns early and never calls
AppLog.install, so this breadcrumb reaches Logcat only, never a
DebugReport. The migration is guard-compliance + Logcat-consistency
only; behavior is unchanged since AppLog forwards to Logcat.

RestartActivity is DEVICE-ONLY (multi-process kill/relaunch), so a
JVM buffer-capture test doesn't apply here. Added
RestartActivityLoggingTest, which instead pins the null-buffer shape
this call runs under in the trampoline process: it forwards to
Logcat and no-ops the buffer cleanly.

Closes #330
Part of #324

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-04 21:09:22 -05:00
co-authored by Claude Opus 4.8
parent 41015a5c40
commit d92d4c1a14
2 changed files with 57 additions and 2 deletions
@@ -5,7 +5,7 @@ import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.os.Process
import android.util.Log
import org.libremail.reporting.AppLog
/**
* Separate-process trampoline that performs an app relaunch from OUTSIDE the process being killed.
@@ -40,7 +40,10 @@ class RestartActivity : Activity() {
if (launchIntent != null) {
startActivity(launchIntent)
} else {
Log.w(TAG, "no launch intent for $packageName; cannot relaunch after restart")
// Logcat-only here: this runs in the ":restart" trampoline process, where
// LibreMailApplication.onCreate returns early and never calls AppLog.install, so the
// buffer is null and this breadcrumb never reaches a DebugReport.
AppLog.w(TAG, "no launch intent for $packageName; cannot relaunch after restart")
}
finish()
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: GPL-3.0-or-later
package org.libremail.restart
import android.util.Log
import io.mockk.every
import io.mockk.mockkStatic
import io.mockk.unmockkAll
import io.mockk.verify
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.libremail.reporting.AppLog
import kotlin.test.assertNull
/**
* Pins the #330 migration of [RestartActivity]'s one log site from raw `Log.w` to [AppLog.w].
* [RestartActivity] itself is DEVICE-ONLY (multi-process kill/relaunch; see its KDoc) and can't be
* exercised in a JVM test, so this characterizes the call it now makes instead of the class itself.
*
* That call runs in the ":restart" trampoline process, where `LibreMailApplication.onCreate` returns
* early and never reaches `AppLog.install` — so [AppLog]'s buffer is null there, and this breadcrumb
* reaches Logcat only, never a `DebugReport`. This is the one migrated site in the #324 epic whose
* "buffer captured the breadcrumb" assertion intentionally does not apply (see #330); instead this
* asserts the null-buffer shape: the call still forwards to Logcat and no-ops cleanly, matching the
* raw `Log.w` behavior it replaced.
*/
class RestartActivityLoggingTest {
// Mirrors RestartActivity's private TAG/message exactly (kept private there; duplicated here
// rather than widening its visibility just for this test).
private val tag = "LibreMailRestart"
private val message = "no launch intent for org.libremail.app; cannot relaunch after restart"
@Before
fun setUp() {
mockkStatic(Log::class)
every { Log.w(any<String>(), any<String>()) } returns 0
AppLog::class.java.getDeclaredField("buffer").apply { isAccessible = true }.set(AppLog, null)
}
@After
fun tearDown() = unmockkAll()
@Test
fun `RestartActivity's no-launch-intent warning forwards to Logcat and no-ops with no buffer installed`() {
AppLog.w(tag, message)
verify { Log.w(tag, message) }
val bufferField = AppLog::class.java.getDeclaredField("buffer").apply { isAccessible = true }
assertNull(bufferField.get(AppLog), "the :restart process never installs a buffer; AppLog must not create one")
}
}