From 397da93458530e0ab9e09904986c6c9adac9b3d6 Mon Sep 17 00:00:00 2001 From: Caitlin Shkuratov Date: Thu, 23 Mar 2023 15:56:13 +0000 Subject: [PATCH] [Table logging] Add "**" to logs that were generated when a flow was initially collected. Fixes: 272518407 Test: `adb shell dumpsys activity service com.android.systemui/.SystemUIService WifiTableLog` -> see ** on the starting values, then don't see ** on the rest of the values Test: same for `MobileSummaryLog` Test: same for `MobileConnectionLog[5]` (5 = my personal sub ID) Test: atest LogDiffsForTableTest TableChangeTest TableLogBufferTest Change-Id: I6d23f02c13dad77f4b2aa63fff2f37105512f79d --- .../android/systemui/log/table/Diffable.kt | 19 ++- .../android/systemui/log/table/TableChange.kt | 28 ++-- .../systemui/log/table/TableLogBuffer.kt | 97 ++++++++++--- .../KeyguardBouncerRepositoryTest.kt | 4 +- .../log/table/LogDiffsForTableTest.kt | 92 ++++++++++-- .../systemui/log/table/TableChangeTest.kt | 135 ++++++++++++++++-- .../systemui/log/table/TableLogBufferTest.kt | 130 ++++++++++++++++- .../FullMobileConnectionRepositoryTest.kt | 8 +- 8 files changed, 450 insertions(+), 63 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt b/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt index ccd406001253a..565bf241a1946 100644 --- a/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt +++ b/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt @@ -70,7 +70,9 @@ fun > Flow.logDiffsForTable( ): Flow { // Fully log the initial value to the table. val getInitialValue = { - tableLogBuffer.logChange(columnPrefix) { row -> initialValue.logFull(row) } + tableLogBuffer.logChange(columnPrefix, isInitial = true) { row -> + initialValue.logFull(row) + } initialValue } return this.pairwiseBy(getInitialValue) { prevVal: T, newVal: T -> @@ -90,7 +92,7 @@ fun Flow.logDiffsForTable( initialValue: Boolean, ): Flow { val initialValueFun = { - tableLogBuffer.logChange(columnPrefix, columnName, initialValue) + tableLogBuffer.logChange(columnPrefix, columnName, initialValue, isInitial = true) initialValue } return this.pairwiseBy(initialValueFun) { prevVal, newVal: Boolean -> @@ -109,7 +111,7 @@ fun Flow.logDiffsForTable( initialValue: Int, ): Flow { val initialValueFun = { - tableLogBuffer.logChange(columnPrefix, columnName, initialValue) + tableLogBuffer.logChange(columnPrefix, columnName, initialValue, isInitial = true) initialValue } return this.pairwiseBy(initialValueFun) { prevVal, newVal: Int -> @@ -128,7 +130,7 @@ fun Flow.logDiffsForTable( initialValue: Int?, ): Flow { val initialValueFun = { - tableLogBuffer.logChange(columnPrefix, columnName, initialValue) + tableLogBuffer.logChange(columnPrefix, columnName, initialValue, isInitial = true) initialValue } return this.pairwiseBy(initialValueFun) { prevVal, newVal: Int? -> @@ -147,7 +149,7 @@ fun Flow.logDiffsForTable( initialValue: String?, ): Flow { val initialValueFun = { - tableLogBuffer.logChange(columnPrefix, columnName, initialValue) + tableLogBuffer.logChange(columnPrefix, columnName, initialValue, isInitial = true) initialValue } return this.pairwiseBy(initialValueFun) { prevVal, newVal: String? -> @@ -166,7 +168,12 @@ fun Flow>.logDiffsForTable( initialValue: List, ): Flow> { val initialValueFun = { - tableLogBuffer.logChange(columnPrefix, columnName, initialValue.toString()) + tableLogBuffer.logChange( + columnPrefix, + columnName, + initialValue.toString(), + isInitial = true, + ) initialValue } return this.pairwiseBy(initialValueFun) { prevVal, newVal: List -> diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt index b73ddc50f831a..42fdd689df6ce 100644 --- a/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt +++ b/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt @@ -16,25 +16,31 @@ package com.android.systemui.log.table +import androidx.annotation.VisibleForTesting + /** * A object used with [TableLogBuffer] to store changes in variables over time. Is recyclable. * * Each message represents a change to exactly 1 type, specified by [DataType]. + * + * @property isInitial see [TableLogBuffer.logChange(String, Boolean, (TableRowLogger) -> Unit]. */ data class TableChange( var timestamp: Long = 0, var columnPrefix: String = "", var columnName: String = "", + var isInitial: Boolean = false, var type: DataType = DataType.EMPTY, var bool: Boolean = false, var int: Int? = null, var str: String? = null, ) { /** Resets to default values so that the object can be recycled. */ - fun reset(timestamp: Long, columnPrefix: String, columnName: String) { + fun reset(timestamp: Long, columnPrefix: String, columnName: String, isInitial: Boolean) { this.timestamp = timestamp this.columnPrefix = columnPrefix this.columnName = columnName + this.isInitial = isInitial this.type = DataType.EMPTY this.bool = false this.int = 0 @@ -61,7 +67,7 @@ data class TableChange( /** Updates this to store the same value as [change]. */ fun updateTo(change: TableChange) { - reset(change.timestamp, change.columnPrefix, change.columnName) + reset(change.timestamp, change.columnPrefix, change.columnName, change.isInitial) when (change.type) { DataType.STRING -> set(change.str) DataType.INT -> set(change.int) @@ -84,12 +90,14 @@ data class TableChange( } fun getVal(): String { - return when (type) { - DataType.EMPTY -> null - DataType.STRING -> str - DataType.INT -> int - DataType.BOOLEAN -> bool - }.toString() + val value = + when (type) { + DataType.EMPTY -> null + DataType.STRING -> str + DataType.INT -> int + DataType.BOOLEAN -> bool + }.toString() + return "${if (isInitial) IS_INITIAL_PREFIX else ""}$value" } enum class DataType { @@ -98,4 +106,8 @@ data class TableChange( INT, EMPTY, } + + companion object { + @VisibleForTesting const val IS_INITIAL_PREFIX = "**" + } } diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt index a0f1c959aed66..9d2d3553db6d6 100644 --- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt +++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt @@ -97,7 +97,13 @@ class TableLogBuffer( // A [TableRowLogger] object, re-used each time [logDiffs] is called. // (Re-used to avoid object allocation.) - private val tempRow = TableRowLoggerImpl(0, columnPrefix = "", this) + private val tempRow = + TableRowLoggerImpl( + timestamp = 0, + columnPrefix = "", + isInitial = false, + tableLogBuffer = this, + ) /** * Log the differences between [prevVal] and [newVal]. @@ -115,6 +121,8 @@ class TableLogBuffer( val row = tempRow row.timestamp = systemClock.currentTimeMillis() row.columnPrefix = columnPrefix + // Because we have a prevVal and a newVal, we know that this isn't the initial log. + row.isInitial = false newVal.logDiffs(prevVal, row) } @@ -123,50 +131,89 @@ class TableLogBuffer( * * @param rowInitializer a function that will be called immediately to store relevant data on * the row. + * @param isInitial true if this change represents the starting value for a particular column + * (as opposed to a value that was updated after receiving new information). This is used to + * help us identify which values were just default starting values, and which values were + * derived from updated information. Most callers should use false for this value. */ @Synchronized - fun logChange(columnPrefix: String, rowInitializer: (TableRowLogger) -> Unit) { + fun logChange( + columnPrefix: String, + isInitial: Boolean = false, + rowInitializer: (TableRowLogger) -> Unit + ) { val row = tempRow row.timestamp = systemClock.currentTimeMillis() row.columnPrefix = columnPrefix + row.isInitial = isInitial rowInitializer(row) } - /** Logs a String? change. */ - fun logChange(prefix: String, columnName: String, value: String?) { - logChange(systemClock.currentTimeMillis(), prefix, columnName, value) + /** + * Logs a String? change. + * + * @param isInitial see [TableLogBuffer.logChange(String, Boolean, (TableRowLogger) -> Unit]. + */ + fun logChange(prefix: String, columnName: String, value: String?, isInitial: Boolean = false) { + logChange(systemClock.currentTimeMillis(), prefix, columnName, value, isInitial) } - /** Logs a boolean change. */ - fun logChange(prefix: String, columnName: String, value: Boolean) { - logChange(systemClock.currentTimeMillis(), prefix, columnName, value) + /** + * Logs a boolean change. + * + * @param isInitial see [TableLogBuffer.logChange(String, Boolean, (TableRowLogger) -> Unit]. + */ + fun logChange(prefix: String, columnName: String, value: Boolean, isInitial: Boolean = false) { + logChange(systemClock.currentTimeMillis(), prefix, columnName, value, isInitial) } - /** Logs a Int change. */ - fun logChange(prefix: String, columnName: String, value: Int?) { - logChange(systemClock.currentTimeMillis(), prefix, columnName, value) + /** + * Logs a Int change. + * + * @param isInitial see [TableLogBuffer.logChange(String, Boolean, (TableRowLogger) -> Unit]. + */ + fun logChange(prefix: String, columnName: String, value: Int?, isInitial: Boolean = false) { + logChange(systemClock.currentTimeMillis(), prefix, columnName, value, isInitial) } // Keep these individual [logChange] methods private (don't let clients give us their own // timestamps.) - private fun logChange(timestamp: Long, prefix: String, columnName: String, value: String?) { + private fun logChange( + timestamp: Long, + prefix: String, + columnName: String, + value: String?, + isInitial: Boolean, + ) { Trace.beginSection("TableLogBuffer#logChange(string)") - val change = obtain(timestamp, prefix, columnName) + val change = obtain(timestamp, prefix, columnName, isInitial) change.set(value) Trace.endSection() } - private fun logChange(timestamp: Long, prefix: String, columnName: String, value: Boolean) { + private fun logChange( + timestamp: Long, + prefix: String, + columnName: String, + value: Boolean, + isInitial: Boolean, + ) { Trace.beginSection("TableLogBuffer#logChange(boolean)") - val change = obtain(timestamp, prefix, columnName) + val change = obtain(timestamp, prefix, columnName, isInitial) change.set(value) Trace.endSection() } - private fun logChange(timestamp: Long, prefix: String, columnName: String, value: Int?) { + private fun logChange( + timestamp: Long, + prefix: String, + columnName: String, + value: Int?, + isInitial: Boolean, + ) { Trace.beginSection("TableLogBuffer#logChange(int)") - val change = obtain(timestamp, prefix, columnName) + val change = obtain(timestamp, prefix, columnName, isInitial) change.set(value) Trace.endSection() } @@ -174,13 +221,18 @@ class TableLogBuffer( // TODO(b/259454430): Add additional change types here. @Synchronized - private fun obtain(timestamp: Long, prefix: String, columnName: String): TableChange { + private fun obtain( + timestamp: Long, + prefix: String, + columnName: String, + isInitial: Boolean, + ): TableChange { verifyValidName(prefix, columnName) val tableChange = buffer.advance() if (tableChange.hasData()) { saveEvictedValue(tableChange) } - tableChange.reset(timestamp, prefix, columnName) + tableChange.reset(timestamp, prefix, columnName, isInitial) return tableChange } @@ -240,21 +292,22 @@ class TableLogBuffer( private class TableRowLoggerImpl( var timestamp: Long, var columnPrefix: String, + var isInitial: Boolean, val tableLogBuffer: TableLogBuffer, ) : TableRowLogger { /** Logs a change to a string value. */ override fun logChange(columnName: String, value: String?) { - tableLogBuffer.logChange(timestamp, columnPrefix, columnName, value) + tableLogBuffer.logChange(timestamp, columnPrefix, columnName, value, isInitial) } /** Logs a change to a boolean value. */ override fun logChange(columnName: String, value: Boolean) { - tableLogBuffer.logChange(timestamp, columnPrefix, columnName, value) + tableLogBuffer.logChange(timestamp, columnPrefix, columnName, value, isInitial) } /** Logs a change to an int value. */ override fun logChange(columnName: String, value: Int) { - tableLogBuffer.logChange(timestamp, columnPrefix, columnName, value) + tableLogBuffer.logChange(timestamp, columnPrefix, columnName, value, isInitial) } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt index e468cc1222ad4..657ee20475d86 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt @@ -21,6 +21,8 @@ import androidx.test.filters.SmallTest import com.android.keyguard.ViewMediatorCallback import com.android.systemui.SysuiTestCase import com.android.systemui.log.table.TableLogBuffer +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.SystemClock import kotlinx.coroutines.runBlocking import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -58,6 +60,6 @@ class KeyguardBouncerRepositoryTest : SysuiTestCase() { @Test fun changingFlowValueTriggersLogging() = runBlocking { underTest.setPrimaryShow(true) - verify(bouncerLogger).logChange("", "PrimaryBouncerShow", false) + verify(bouncerLogger).logChange(eq(""), eq("PrimaryBouncerShow"), value = eq(false), any()) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt index d1744c61de587..c49337a53970a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.log.table import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.log.table.TableChange.Companion.IS_INITIAL_PREFIX import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import java.io.PrintWriter @@ -91,6 +92,7 @@ class LogDiffsForTableTest : SysuiTestCase() { SEPARATOR + FULL_NAME + SEPARATOR + + IS_INITIAL_PREFIX + "false" ) @@ -121,7 +123,12 @@ class LogDiffsForTableTest : SysuiTestCase() { val logs = dumpLog() assertThat(logs) .contains( - TABLE_LOG_DATE_FORMAT.format(100L) + SEPARATOR + FULL_NAME + SEPARATOR + "false" + TABLE_LOG_DATE_FORMAT.format(100L) + + SEPARATOR + + FULL_NAME + + SEPARATOR + + IS_INITIAL_PREFIX + + "false" ) assertThat(logs) .contains( @@ -164,7 +171,12 @@ class LogDiffsForTableTest : SysuiTestCase() { // Input flow: true@100, true@200, true@300, false@400, false@500, true@600 // Output log: true@100, --------, --------, false@400, ---------, true@600 val expected1 = - TABLE_LOG_DATE_FORMAT.format(100L) + SEPARATOR + FULL_NAME + SEPARATOR + "true" + TABLE_LOG_DATE_FORMAT.format(100L) + + SEPARATOR + + FULL_NAME + + SEPARATOR + + IS_INITIAL_PREFIX + + "true" val expected4 = TABLE_LOG_DATE_FORMAT.format(400L) + SEPARATOR + FULL_NAME + SEPARATOR + "false" val expected6 = @@ -203,7 +215,12 @@ class LogDiffsForTableTest : SysuiTestCase() { val job = launch { flowWithLogging.collect() } assertThat(dumpLog()) .contains( - TABLE_LOG_DATE_FORMAT.format(50L) + SEPARATOR + FULL_NAME + SEPARATOR + "false" + TABLE_LOG_DATE_FORMAT.format(50L) + + SEPARATOR + + FULL_NAME + + SEPARATOR + + IS_INITIAL_PREFIX + + "false" ) systemClock.setCurrentTimeMillis(100L) @@ -269,7 +286,12 @@ class LogDiffsForTableTest : SysuiTestCase() { val logs = dumpLog() assertThat(logs) .contains( - TABLE_LOG_DATE_FORMAT.format(3000L) + SEPARATOR + FULL_NAME + SEPARATOR + "1234" + TABLE_LOG_DATE_FORMAT.format(3000L) + + SEPARATOR + + FULL_NAME + + SEPARATOR + + IS_INITIAL_PREFIX + + "1234" ) job.cancel() @@ -299,7 +321,12 @@ class LogDiffsForTableTest : SysuiTestCase() { val logs = dumpLog() assertThat(logs) .contains( - TABLE_LOG_DATE_FORMAT.format(100L) + SEPARATOR + FULL_NAME + SEPARATOR + "1234" + TABLE_LOG_DATE_FORMAT.format(100L) + + SEPARATOR + + FULL_NAME + + SEPARATOR + + IS_INITIAL_PREFIX + + "1234" ) assertThat(logs) .contains( @@ -345,7 +372,12 @@ class LogDiffsForTableTest : SysuiTestCase() { val logs = dumpLog() assertThat(logs) .contains( - TABLE_LOG_DATE_FORMAT.format(100L) + SEPARATOR + FULL_NAME + SEPARATOR + "1" + TABLE_LOG_DATE_FORMAT.format(100L) + + SEPARATOR + + FULL_NAME + + SEPARATOR + + IS_INITIAL_PREFIX + + "1" ) assertThat(logs) .contains( @@ -388,7 +420,12 @@ class LogDiffsForTableTest : SysuiTestCase() { // Input flow: 1@100, 2@200, 3@300, 3@400, 3@500, 2@600, 6@700, 6@800 // Output log: 1@100, 2@200, 3@300, -----, -----, 2@600, 6@700, ----- val expected1 = - TABLE_LOG_DATE_FORMAT.format(100L) + SEPARATOR + FULL_NAME + SEPARATOR + "1" + TABLE_LOG_DATE_FORMAT.format(100L) + + SEPARATOR + + FULL_NAME + + SEPARATOR + + IS_INITIAL_PREFIX + + "1" val expected2 = TABLE_LOG_DATE_FORMAT.format(200L) + SEPARATOR + FULL_NAME + SEPARATOR + "2" val expected3 = @@ -432,7 +469,12 @@ class LogDiffsForTableTest : SysuiTestCase() { val job = launch { flowWithLogging.collect() } assertThat(dumpLog()) .contains( - TABLE_LOG_DATE_FORMAT.format(50L) + SEPARATOR + FULL_NAME + SEPARATOR + "1111" + TABLE_LOG_DATE_FORMAT.format(50L) + + SEPARATOR + + FULL_NAME + + SEPARATOR + + IS_INITIAL_PREFIX + + "1111" ) systemClock.setCurrentTimeMillis(100L) @@ -502,6 +544,7 @@ class LogDiffsForTableTest : SysuiTestCase() { SEPARATOR + FULL_NAME + SEPARATOR + + IS_INITIAL_PREFIX + "val1234" ) @@ -532,7 +575,12 @@ class LogDiffsForTableTest : SysuiTestCase() { val logs = dumpLog() assertThat(logs) .contains( - TABLE_LOG_DATE_FORMAT.format(100L) + SEPARATOR + FULL_NAME + SEPARATOR + "val1" + TABLE_LOG_DATE_FORMAT.format(100L) + + SEPARATOR + + FULL_NAME + + SEPARATOR + + IS_INITIAL_PREFIX + + "val1" ) assertThat(logs) .contains( @@ -574,7 +622,12 @@ class LogDiffsForTableTest : SysuiTestCase() { val logs = dumpLog() assertThat(logs) .contains( - TABLE_LOG_DATE_FORMAT.format(100L) + SEPARATOR + FULL_NAME + SEPARATOR + "start" + TABLE_LOG_DATE_FORMAT.format(100L) + + SEPARATOR + + FULL_NAME + + SEPARATOR + + IS_INITIAL_PREFIX + + "start" ) assertThat(logs) .contains( @@ -621,7 +674,12 @@ class LogDiffsForTableTest : SysuiTestCase() { // Input flow: start@100, start@200, new@300, new@400, newer@500, newest@600, newest@700 // Output log: start@100, ---------, new@300, -------, newer@500, newest@600, ---------- val expected1 = - TABLE_LOG_DATE_FORMAT.format(100L) + SEPARATOR + FULL_NAME + SEPARATOR + "start" + TABLE_LOG_DATE_FORMAT.format(100L) + + SEPARATOR + + FULL_NAME + + SEPARATOR + + IS_INITIAL_PREFIX + + "start" val expected3 = TABLE_LOG_DATE_FORMAT.format(300L) + SEPARATOR + FULL_NAME + SEPARATOR + "new" val expected5 = @@ -667,6 +725,7 @@ class LogDiffsForTableTest : SysuiTestCase() { SEPARATOR + FULL_NAME + SEPARATOR + + IS_INITIAL_PREFIX + "initial" ) @@ -761,6 +820,7 @@ class LogDiffsForTableTest : SysuiTestCase() { "." + TestDiffable.COL_FULL + SEPARATOR + + IS_INITIAL_PREFIX + "true" ) assertThat(logs) @@ -771,6 +831,7 @@ class LogDiffsForTableTest : SysuiTestCase() { "." + TestDiffable.COL_INT + SEPARATOR + + IS_INITIAL_PREFIX + "1234" ) assertThat(logs) @@ -781,6 +842,7 @@ class LogDiffsForTableTest : SysuiTestCase() { "." + TestDiffable.COL_STRING + SEPARATOR + + IS_INITIAL_PREFIX + "string1234" ) assertThat(logs) @@ -791,6 +853,7 @@ class LogDiffsForTableTest : SysuiTestCase() { "." + TestDiffable.COL_BOOLEAN + SEPARATOR + + IS_INITIAL_PREFIX + "false" ) job.cancel() @@ -979,6 +1042,7 @@ class LogDiffsForTableTest : SysuiTestCase() { "." + TestDiffable.COL_INT + SEPARATOR + + IS_INITIAL_PREFIX + "0" ) assertThat(logs) @@ -989,6 +1053,7 @@ class LogDiffsForTableTest : SysuiTestCase() { "." + TestDiffable.COL_STRING + SEPARATOR + + IS_INITIAL_PREFIX + "string0" ) assertThat(logs) @@ -999,6 +1064,7 @@ class LogDiffsForTableTest : SysuiTestCase() { "." + TestDiffable.COL_BOOLEAN + SEPARATOR + + IS_INITIAL_PREFIX + "false" ) @@ -1118,6 +1184,7 @@ class LogDiffsForTableTest : SysuiTestCase() { SEPARATOR + FULL_NAME + SEPARATOR + + IS_INITIAL_PREFIX + listOf(1234).toString() ) @@ -1155,6 +1222,7 @@ class LogDiffsForTableTest : SysuiTestCase() { SEPARATOR + FULL_NAME + SEPARATOR + + IS_INITIAL_PREFIX + listOf("val0", "val00").toString() ) assertThat(logs) @@ -1221,6 +1289,7 @@ class LogDiffsForTableTest : SysuiTestCase() { SEPARATOR + FULL_NAME + SEPARATOR + + IS_INITIAL_PREFIX + listOf("val0", "val00").toString() val expected3 = TABLE_LOG_DATE_FORMAT.format(300L) + @@ -1276,6 +1345,7 @@ class LogDiffsForTableTest : SysuiTestCase() { SEPARATOR + FULL_NAME + SEPARATOR + + IS_INITIAL_PREFIX + listOf(1111).toString() ) diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt index fb20bacee64c2..a003e1d9d1f3f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.log.table import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.log.table.TableChange.Companion.IS_INITIAL_PREFIX import com.google.common.truth.Truth.assertThat import org.junit.Test @@ -28,7 +29,12 @@ class TableChangeTest : SysuiTestCase() { fun setString_isString() { val underTest = TableChange() - underTest.reset(timestamp = 100, columnPrefix = "", columnName = "fakeName") + underTest.reset( + timestamp = 100, + columnPrefix = "", + columnName = "fakeName", + isInitial = false, + ) underTest.set("fakeValue") assertThat(underTest.hasData()).isTrue() @@ -39,7 +45,12 @@ class TableChangeTest : SysuiTestCase() { fun setString_null() { val underTest = TableChange() - underTest.reset(timestamp = 100, columnPrefix = "", columnName = "fakeName") + underTest.reset( + timestamp = 100, + columnPrefix = "", + columnName = "fakeName", + isInitial = false, + ) underTest.set(null as String?) assertThat(underTest.hasData()).isTrue() @@ -50,7 +61,12 @@ class TableChangeTest : SysuiTestCase() { fun setBoolean_isBoolean() { val underTest = TableChange() - underTest.reset(timestamp = 100, columnPrefix = "", columnName = "fakeName") + underTest.reset( + timestamp = 100, + columnPrefix = "", + columnName = "fakeName", + isInitial = false, + ) underTest.set(true) assertThat(underTest.hasData()).isTrue() @@ -61,7 +77,12 @@ class TableChangeTest : SysuiTestCase() { fun setInt_isInt() { val underTest = TableChange() - underTest.reset(timestamp = 100, columnPrefix = "", columnName = "fakeName") + underTest.reset( + timestamp = 100, + columnPrefix = "", + columnName = "fakeName", + isInitial = false, + ) underTest.set(8900) assertThat(underTest.hasData()).isTrue() @@ -72,7 +93,12 @@ class TableChangeTest : SysuiTestCase() { fun setInt_null() { val underTest = TableChange() - underTest.reset(timestamp = 100, columnPrefix = "", columnName = "fakeName") + underTest.reset( + timestamp = 100, + columnPrefix = "", + columnName = "fakeName", + isInitial = false, + ) underTest.set(null as Int?) assertThat(underTest.hasData()).isTrue() @@ -83,9 +109,19 @@ class TableChangeTest : SysuiTestCase() { fun setThenReset_isEmpty() { val underTest = TableChange() - underTest.reset(timestamp = 100, columnPrefix = "", columnName = "fakeName") + underTest.reset( + timestamp = 100, + columnPrefix = "", + columnName = "fakeName", + isInitial = false, + ) underTest.set(8900) - underTest.reset(timestamp = 0, columnPrefix = "prefix", columnName = "name") + underTest.reset( + timestamp = 0, + columnPrefix = "prefix", + columnName = "name", + isInitial = false, + ) assertThat(underTest.hasData()).isFalse() assertThat(underTest.getVal()).isEqualTo("null") @@ -106,13 +142,34 @@ class TableChangeTest : SysuiTestCase() { assertThat(underTest.getName()).contains("fakeName") } + @Test + fun getVal_notInitial() { + val underTest = TableChange(columnName = "name", isInitial = false) + underTest.set("testValue") + + assertThat(underTest.getVal()).isEqualTo("testValue") + } + + @Test + fun getVal_isInitial() { + val underTest = TableChange(columnName = "name", isInitial = true) + underTest.set("testValue") + + assertThat(underTest.getVal()).isEqualTo("${IS_INITIAL_PREFIX}testValue") + } + @Test fun resetThenSet_hasNewValue() { val underTest = TableChange() - underTest.reset(timestamp = 100, columnPrefix = "prefix", columnName = "original") + underTest.reset( + timestamp = 100, + columnPrefix = "prefix", + columnName = "original", + isInitial = false, + ) underTest.set("fakeValue") - underTest.reset(timestamp = 0, columnPrefix = "", columnName = "updated") + underTest.reset(timestamp = 0, columnPrefix = "", columnName = "updated", isInitial = false) underTest.set(8900) assertThat(underTest.hasData()).isTrue() @@ -122,6 +179,40 @@ class TableChangeTest : SysuiTestCase() { assertThat(underTest.getVal()).isEqualTo("8900") } + @Test + fun reset_initialToNotInitial_valDoesNotHaveInitial() { + val underTest = TableChange() + + underTest.reset( + timestamp = 100, + columnPrefix = "prefix", + columnName = "original", + isInitial = true, + ) + underTest.set("fakeValue") + underTest.reset(timestamp = 0, columnPrefix = "", columnName = "updated", isInitial = false) + underTest.set(8900) + + assertThat(underTest.getVal()).doesNotContain(IS_INITIAL_PREFIX) + } + + @Test + fun reset_notInitialToInitial_valHasInitial() { + val underTest = TableChange() + + underTest.reset( + timestamp = 100, + columnPrefix = "prefix", + columnName = "original", + isInitial = false, + ) + underTest.set("fakeValue") + underTest.reset(timestamp = 0, columnPrefix = "", columnName = "updated", isInitial = true) + underTest.set(8900) + + assertThat(underTest.getVal()).contains(IS_INITIAL_PREFIX) + } + @Test fun updateTo_emptyToString_isString() { val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName") @@ -209,4 +300,30 @@ class TableChangeTest : SysuiTestCase() { assertThat(underTest.getName()).contains("newName") assertThat(underTest.getVal()).isEqualTo("true") } + + @Test + fun updateTo_notInitialToInitial_isInitial() { + val underTest = + TableChange(columnPrefix = "fakePrefix", columnName = "fakeName", isInitial = false) + underTest.set(false) + + val new = TableChange(columnPrefix = "newPrefix", columnName = "newName", isInitial = true) + new.set(true) + underTest.updateTo(new) + + assertThat(underTest.getVal()).contains(IS_INITIAL_PREFIX) + } + + @Test + fun updateTo_initialToNotInitial_isNotInitial() { + val underTest = + TableChange(columnPrefix = "fakePrefix", columnName = "fakeName", isInitial = true) + underTest.set(false) + + val new = TableChange(columnPrefix = "newPrefix", columnName = "newName", isInitial = false) + new.set(true) + underTest.updateTo(new) + + assertThat(underTest.getVal()).doesNotContain(IS_INITIAL_PREFIX) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt index 949fa1cce0cb1..aed830ae0d539 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.log.table import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.log.table.TableChange.Companion.IS_INITIAL_PREFIX import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import java.io.PrintWriter @@ -353,10 +354,10 @@ class TableLogBufferTest : SysuiTestCase() { } @Test - fun logChange_rowInitializer_dumpsCorrectly() { + fun logChange_rowInitializer_notIsInitial_dumpsCorrectly() { systemClock.setCurrentTimeMillis(100L) - underTest.logChange("") { row -> + underTest.logChange(columnPrefix = "", isInitial = false) { row -> row.logChange("column1", "val1") row.logChange("column2", 2) row.logChange("column3", true) @@ -373,6 +374,131 @@ class TableLogBufferTest : SysuiTestCase() { assertThat(dumpedString).contains(expected3) } + @Test + fun logChange_rowInitializer_isInitial_dumpsCorrectly() { + systemClock.setCurrentTimeMillis(100L) + + underTest.logChange(columnPrefix = "", isInitial = true) { row -> + row.logChange("column1", "val1") + row.logChange("column2", 2) + row.logChange("column3", true) + } + + val dumpedString = dumpChanges() + + val timestamp = TABLE_LOG_DATE_FORMAT.format(100L) + val expected1 = timestamp + SEPARATOR + "column1" + SEPARATOR + IS_INITIAL_PREFIX + "val1" + val expected2 = timestamp + SEPARATOR + "column2" + SEPARATOR + IS_INITIAL_PREFIX + "2" + val expected3 = timestamp + SEPARATOR + "column3" + SEPARATOR + IS_INITIAL_PREFIX + "true" + assertThat(dumpedString).contains(expected1) + assertThat(dumpedString).contains(expected2) + assertThat(dumpedString).contains(expected3) + } + + @Test + fun logChange_rowInitializer_isInitialThenNotInitial_dumpsCorrectly() { + systemClock.setCurrentTimeMillis(100L) + underTest.logChange(columnPrefix = "", isInitial = true) { row -> + row.logChange("column1", "val1") + row.logChange("column2", 2) + row.logChange("column3", true) + } + + systemClock.setCurrentTimeMillis(200L) + underTest.logChange(columnPrefix = "", isInitial = false) { row -> + row.logChange("column1", "val11") + row.logChange("column2", 22) + row.logChange("column3", false) + } + + val dumpedString = dumpChanges() + + val timestamp = TABLE_LOG_DATE_FORMAT.format(100L) + val expected1 = timestamp + SEPARATOR + "column1" + SEPARATOR + IS_INITIAL_PREFIX + "val1" + val expected2 = timestamp + SEPARATOR + "column2" + SEPARATOR + IS_INITIAL_PREFIX + "2" + val expected3 = timestamp + SEPARATOR + "column3" + SEPARATOR + IS_INITIAL_PREFIX + "true" + val timestamp2 = TABLE_LOG_DATE_FORMAT.format(200L) + val expected4 = timestamp2 + SEPARATOR + "column1" + SEPARATOR + "val11" + val expected5 = timestamp2 + SEPARATOR + "column2" + SEPARATOR + "22" + val expected6 = timestamp2 + SEPARATOR + "column3" + SEPARATOR + "false" + assertThat(dumpedString).contains(expected1) + assertThat(dumpedString).contains(expected2) + assertThat(dumpedString).contains(expected3) + assertThat(dumpedString).contains(expected4) + assertThat(dumpedString).contains(expected5) + assertThat(dumpedString).contains(expected6) + } + + @Test + fun logDiffs_neverInitial() { + systemClock.setCurrentTimeMillis(100L) + + val prevDiffable = + object : TestDiffable() { + override fun logDiffs(prevVal: TestDiffable, row: TableRowLogger) { + row.logChange("stringValChange", "prevStringVal") + } + } + val nextDiffable = + object : TestDiffable() { + override fun logDiffs(prevVal: TestDiffable, row: TableRowLogger) { + row.logChange("stringValChange", "newStringVal") + } + } + + underTest.logDiffs("prefix", prevDiffable, nextDiffable) + + val dumpedString = dumpChanges() + + assertThat(dumpedString).doesNotContain(IS_INITIAL_PREFIX) + } + + @Test + fun logChange_variousPrimitiveValues_isInitialAlwaysUpdated() { + systemClock.setCurrentTimeMillis(100L) + underTest.logChange(prefix = "", columnName = "first", value = "val1", isInitial = true) + systemClock.setCurrentTimeMillis(200L) + underTest.logChange(prefix = "", columnName = "second", value = "val2", isInitial = true) + systemClock.setCurrentTimeMillis(300L) + underTest.logChange(prefix = "", columnName = "first", value = 11, isInitial = false) + systemClock.setCurrentTimeMillis(400L) + underTest.logChange(prefix = "", columnName = "first", value = false, isInitial = false) + systemClock.setCurrentTimeMillis(500L) + underTest.logChange(prefix = "", columnName = "third", value = 33, isInitial = true) + + val dumpedString = dumpChanges() + + val expected1 = + TABLE_LOG_DATE_FORMAT.format(100L) + + SEPARATOR + + "first" + + SEPARATOR + + IS_INITIAL_PREFIX + + "val1" + val expected2 = + TABLE_LOG_DATE_FORMAT.format(200L) + + SEPARATOR + + "second" + + SEPARATOR + + IS_INITIAL_PREFIX + + "val2" + val expected3 = TABLE_LOG_DATE_FORMAT.format(300L) + SEPARATOR + "first" + SEPARATOR + "11" + val expected4 = + TABLE_LOG_DATE_FORMAT.format(400L) + SEPARATOR + "first" + SEPARATOR + "false" + val expected5 = + TABLE_LOG_DATE_FORMAT.format(500L) + + SEPARATOR + + "third" + + SEPARATOR + + IS_INITIAL_PREFIX + + "33" + assertThat(dumpedString).contains(expected1) + assertThat(dumpedString).contains(expected2) + assertThat(dumpedString).contains(expected3) + assertThat(dumpedString).contains(expected4) + assertThat(dumpedString).contains(expected5) + } + @Test fun logChangeAndLogDiffs_bothLogged() { systemClock.setCurrentTimeMillis(100L) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt index db5a7d1ad84a5..f2bb66a501ec1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt @@ -378,24 +378,24 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { // WHEN we set up some mobile connection info val serviceState = ServiceState() serviceState.setOperatorName("longName", "OpTypical", "1") - serviceState.isEmergencyOnly = false + serviceState.isEmergencyOnly = true getTelephonyCallbackForType(telephonyManager) .onServiceStateChanged(serviceState) // THEN it's logged to the buffer assertThat(dumpBuffer()).contains("$COL_OPERATOR${BUFFER_SEPARATOR}OpTypical") - assertThat(dumpBuffer()).contains("$COL_EMERGENCY${BUFFER_SEPARATOR}false") + assertThat(dumpBuffer()).contains("$COL_EMERGENCY${BUFFER_SEPARATOR}true") // WHEN we update mobile connection info val serviceState2 = ServiceState() serviceState2.setOperatorName("longName", "OpDiff", "1") - serviceState2.isEmergencyOnly = true + serviceState2.isEmergencyOnly = false getTelephonyCallbackForType(telephonyManager) .onServiceStateChanged(serviceState2) // THEN the updates are logged assertThat(dumpBuffer()).contains("$COL_OPERATOR${BUFFER_SEPARATOR}OpDiff") - assertThat(dumpBuffer()).contains("$COL_EMERGENCY${BUFFER_SEPARATOR}true") + assertThat(dumpBuffer()).contains("$COL_EMERGENCY${BUFFER_SEPARATOR}false") emergencyJob.cancel() operatorJob.cancel()