Loading packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt +23 −10 Original line number Diff line number Diff line Loading @@ -27,19 +27,27 @@ import androidx.annotation.VisibleForTesting */ 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, private var columnPrefix: String = "", private var columnName: String = "", private var isInitial: Boolean = false, private var type: DataType = DataType.EMPTY, private var bool: Boolean = false, private var int: Int? = null, private var str: String? = null, ) { init { // Truncate any strings that were passed into the constructor. [reset] and [set] will take // care of the rest of the truncation. this.columnPrefix = columnPrefix.take(MAX_STRING_LENGTH) this.columnName = columnName.take(MAX_STRING_LENGTH) this.str = str?.take(MAX_STRING_LENGTH) } /** Resets to default values so that the object can be recycled. */ fun reset(timestamp: Long, columnPrefix: String, columnName: String, isInitial: Boolean) { this.timestamp = timestamp this.columnPrefix = columnPrefix this.columnName = columnName this.columnPrefix = columnPrefix.take(MAX_STRING_LENGTH) this.columnName = columnName.take(MAX_STRING_LENGTH) this.isInitial = isInitial this.type = DataType.EMPTY this.bool = false Loading @@ -50,7 +58,7 @@ data class TableChange( /** Sets this to store a string change. */ fun set(value: String?) { type = DataType.STRING str = value str = value?.take(MAX_STRING_LENGTH) } /** Sets this to store a boolean change. */ Loading Loading @@ -89,6 +97,8 @@ data class TableChange( } } fun getColumnName() = columnName fun getVal(): String { val value = when (type) { Loading @@ -109,5 +119,8 @@ data class TableChange( companion object { @VisibleForTesting const val IS_INITIAL_PREFIX = "**" // Don't allow any strings larger than this length so that we have a hard upper limit on the // size of the data stored by the buffer. @VisibleForTesting const val MAX_STRING_LENGTH = 500 } } packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt +1 −1 Original line number Diff line number Diff line Loading @@ -291,7 +291,7 @@ class TableLogBuffer( private fun echoToDesiredEndpoints(change: TableChange) { if ( logcatEchoTracker.isBufferLoggable(bufferName = name, LogLevel.DEBUG) || logcatEchoTracker.isTagLoggable(change.columnName, LogLevel.DEBUG) logcatEchoTracker.isTagLoggable(change.getColumnName(), LogLevel.DEBUG) ) { if (change.hasData()) { localLogcat.d(name, change.logcatRepresentation()) Loading packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt +150 −0 Original line number Diff line number Diff line Loading @@ -19,7 +19,9 @@ 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.log.table.TableChange.Companion.MAX_STRING_LENGTH import com.google.common.truth.Truth.assertThat import junit.framework.Assert.assertTrue import org.junit.Test @SmallTest Loading Loading @@ -326,4 +328,152 @@ class TableChangeTest : SysuiTestCase() { assertThat(underTest.getVal()).doesNotContain(IS_INITIAL_PREFIX) } @Test fun constructor_columnAndValueTooLong_truncated() { val underTest = TableChange( columnPrefix = "P".repeat(MAX_STRING_LENGTH + 10), columnName = "N".repeat(MAX_STRING_LENGTH + 10), type = TableChange.DataType.STRING, str = "V".repeat(MAX_STRING_LENGTH + 10), ) assertThat(underTest.getName()).contains("P".repeat(MAX_STRING_LENGTH)) assertThat(underTest.getName()).doesNotContain("P".repeat(MAX_STRING_LENGTH + 1)) assertThat(underTest.getName()).contains("N".repeat(MAX_STRING_LENGTH)) assertThat(underTest.getName()).doesNotContain("N".repeat(MAX_STRING_LENGTH + 1)) assertThat(underTest.getVal()).isEqualTo("V".repeat(MAX_STRING_LENGTH)) } @Test fun constructor_columnNameNotTooLong_noReallocation() { val inputColumnName = "fakeName" val inputValue = "fakeValue" val underTest = TableChange( columnPrefix = "", columnName = inputColumnName, type = TableChange.DataType.STRING, str = inputValue, ) // Use referential equality to verify we didn't reallocate a new string when the string is // *not* too long. assertTrue(underTest.getColumnName() === inputColumnName) } @Test fun reset_columnPrefixTooLong_truncated() { val underTest = TableChange() underTest.reset( timestamp = 1L, columnPrefix = "P".repeat(MAX_STRING_LENGTH + 10), columnName = "name", isInitial = false, ) assertThat(underTest.getName()).contains("P".repeat(MAX_STRING_LENGTH)) assertThat(underTest.getName()).doesNotContain("P".repeat(MAX_STRING_LENGTH + 1)) } @Test fun reset_columnNameTooLong_truncated() { val underTest = TableChange() underTest.reset( timestamp = 1L, columnPrefix = "prefix", columnName = "N".repeat(MAX_STRING_LENGTH + 10), isInitial = false, ) assertThat(underTest.getName()).contains("N".repeat(MAX_STRING_LENGTH)) assertThat(underTest.getName()).doesNotContain("N".repeat(MAX_STRING_LENGTH + 1)) } @Test fun reset_columnNameNotTooLong_noReallocation() { val underTest = TableChange() val shortColumnName = "shortColumnName" underTest.reset( timestamp = 1L, columnPrefix = "prefix", columnName = shortColumnName, isInitial = false, ) // Use referential equality to verify we didn't reallocate a new string when the string is // *not* too long. assertTrue(underTest.getColumnName() === shortColumnName) } @Test fun setString_valueTooLong_truncated() { val underTest = TableChange() underTest.set("V".repeat(MAX_STRING_LENGTH + 1)) assertThat(underTest.getVal()).isEqualTo("V".repeat(MAX_STRING_LENGTH)) } @Test fun updateTo_newColumnPrefixTooLong_truncated() { val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName") underTest.set(42) val new = TableChange( columnPrefix = "P".repeat(MAX_STRING_LENGTH + 10), columnName = "name", ) underTest.updateTo(new) assertThat(underTest.getName()).contains("P".repeat(MAX_STRING_LENGTH)) assertThat(underTest.getName()).doesNotContain("P".repeat(MAX_STRING_LENGTH + 1)) } @Test fun updateTo_newColumnNameTooLong_truncated() { val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName") underTest.set(42) val new = TableChange( columnPrefix = "prefix", columnName = "N".repeat(MAX_STRING_LENGTH + 10), ) underTest.updateTo(new) assertThat(underTest.getName()).contains("N".repeat(MAX_STRING_LENGTH)) assertThat(underTest.getName()).doesNotContain("N".repeat(MAX_STRING_LENGTH + 1)) } @Test fun updateTo_columnNameNotTooLong_noReallocation() { val underTest = TableChange() val shortColumnName = "shortColumnName" val new = TableChange(columnPrefix = "prefix", columnName = shortColumnName) underTest.updateTo(new) // Use referential equality to verify we didn't reallocate a new string when the string is // *not* too long. assertTrue(underTest.getColumnName() === shortColumnName) } @Test fun updateTo_newValTooLong_truncated() { val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName") underTest.set("value") val new = TableChange() new.set("V".repeat(MAX_STRING_LENGTH + 10)) underTest.updateTo(new) assertThat(underTest.getVal()).isEqualTo("V".repeat(MAX_STRING_LENGTH)) } } packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt +107 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,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.log.table.TableChange.Companion.MAX_STRING_LENGTH import com.android.systemui.plugins.log.LogLevel import com.android.systemui.plugins.log.LogcatEchoTracker import com.android.systemui.util.mockito.any Loading Loading @@ -575,6 +576,112 @@ class TableLogBufferTest : SysuiTestCase() { assertThat(dumpedString).contains(expected6) } @Test fun dumpChanges_tooLongColumnPrefix_viaLogChange_truncated() { underTest.logChange( prefix = "P".repeat(MAX_STRING_LENGTH + 10), columnName = "name", value = true, ) val dumpedString = dumpChanges() assertThat(dumpedString).contains("P".repeat(MAX_STRING_LENGTH)) assertThat(dumpedString).doesNotContain("P".repeat(MAX_STRING_LENGTH + 1)) } @Test fun dumpChanges_tooLongColumnPrefix_viaLogDiffs_truncated() { val prevDiffable = object : TestDiffable() {} val nextDiffable = object : TestDiffable() { override fun logDiffs(prevVal: TestDiffable, row: TableRowLogger) { row.logChange("status", "value") } } // WHEN the column prefix is too large underTest.logDiffs( columnPrefix = "P".repeat(MAX_STRING_LENGTH + 10), prevDiffable, nextDiffable, ) val dumpedString = dumpChanges() // THEN it's truncated to the max length assertThat(dumpedString).contains("P".repeat(MAX_STRING_LENGTH)) assertThat(dumpedString).doesNotContain("P".repeat(MAX_STRING_LENGTH + 1)) } @Test fun dumpChanges_tooLongColumnName_viaLogChange_truncated() { underTest.logChange( prefix = "prefix", columnName = "N".repeat(MAX_STRING_LENGTH + 10), value = 10, ) val dumpedString = dumpChanges() assertThat(dumpedString).contains("N".repeat(MAX_STRING_LENGTH)) assertThat(dumpedString).doesNotContain("N".repeat(MAX_STRING_LENGTH + 1)) } @Test fun dumpChanges_tooLongColumnName_viaLogDiffs_truncated() { val prevDiffable = object : TestDiffable() {} val nextDiffable = object : TestDiffable() { override fun logDiffs(prevVal: TestDiffable, row: TableRowLogger) { // WHEN the column name is too large row.logChange(columnName = "N".repeat(MAX_STRING_LENGTH + 10), "value") } } underTest.logDiffs(columnPrefix = "prefix", prevDiffable, nextDiffable) val dumpedString = dumpChanges() // THEN it's truncated to the max length assertThat(dumpedString).contains("N".repeat(MAX_STRING_LENGTH)) assertThat(dumpedString).doesNotContain("N".repeat(MAX_STRING_LENGTH + 1)) } @Test fun dumpChanges_tooLongValue_viaLogChange_truncated() { underTest.logChange( prefix = "prefix", columnName = "name", value = "V".repeat(MAX_STRING_LENGTH + 10), ) val dumpedString = dumpChanges() assertThat(dumpedString).contains("V".repeat(MAX_STRING_LENGTH)) assertThat(dumpedString).doesNotContain("V".repeat(MAX_STRING_LENGTH + 1)) } @Test fun dumpChanges_tooLongValue_viaLogDiffs_truncated() { val prevDiffable = object : TestDiffable() {} val nextDiffable = object : TestDiffable() { override fun logDiffs(prevVal: TestDiffable, row: TableRowLogger) { // WHEN the value is too large row.logChange("columnName", value = "V".repeat(MAX_STRING_LENGTH + 10)) } } underTest.logDiffs(columnPrefix = "prefix", prevDiffable, nextDiffable) val dumpedString = dumpChanges() // THEN it's truncated to the max length assertThat(dumpedString).contains("V".repeat(MAX_STRING_LENGTH)) assertThat(dumpedString).doesNotContain("V".repeat(MAX_STRING_LENGTH + 1)) } @Test fun dumpChanges_rotatesIfBufferIsFull() { lateinit var valToDump: String Loading Loading
packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt +23 −10 Original line number Diff line number Diff line Loading @@ -27,19 +27,27 @@ import androidx.annotation.VisibleForTesting */ 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, private var columnPrefix: String = "", private var columnName: String = "", private var isInitial: Boolean = false, private var type: DataType = DataType.EMPTY, private var bool: Boolean = false, private var int: Int? = null, private var str: String? = null, ) { init { // Truncate any strings that were passed into the constructor. [reset] and [set] will take // care of the rest of the truncation. this.columnPrefix = columnPrefix.take(MAX_STRING_LENGTH) this.columnName = columnName.take(MAX_STRING_LENGTH) this.str = str?.take(MAX_STRING_LENGTH) } /** Resets to default values so that the object can be recycled. */ fun reset(timestamp: Long, columnPrefix: String, columnName: String, isInitial: Boolean) { this.timestamp = timestamp this.columnPrefix = columnPrefix this.columnName = columnName this.columnPrefix = columnPrefix.take(MAX_STRING_LENGTH) this.columnName = columnName.take(MAX_STRING_LENGTH) this.isInitial = isInitial this.type = DataType.EMPTY this.bool = false Loading @@ -50,7 +58,7 @@ data class TableChange( /** Sets this to store a string change. */ fun set(value: String?) { type = DataType.STRING str = value str = value?.take(MAX_STRING_LENGTH) } /** Sets this to store a boolean change. */ Loading Loading @@ -89,6 +97,8 @@ data class TableChange( } } fun getColumnName() = columnName fun getVal(): String { val value = when (type) { Loading @@ -109,5 +119,8 @@ data class TableChange( companion object { @VisibleForTesting const val IS_INITIAL_PREFIX = "**" // Don't allow any strings larger than this length so that we have a hard upper limit on the // size of the data stored by the buffer. @VisibleForTesting const val MAX_STRING_LENGTH = 500 } }
packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt +1 −1 Original line number Diff line number Diff line Loading @@ -291,7 +291,7 @@ class TableLogBuffer( private fun echoToDesiredEndpoints(change: TableChange) { if ( logcatEchoTracker.isBufferLoggable(bufferName = name, LogLevel.DEBUG) || logcatEchoTracker.isTagLoggable(change.columnName, LogLevel.DEBUG) logcatEchoTracker.isTagLoggable(change.getColumnName(), LogLevel.DEBUG) ) { if (change.hasData()) { localLogcat.d(name, change.logcatRepresentation()) Loading
packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt +150 −0 Original line number Diff line number Diff line Loading @@ -19,7 +19,9 @@ 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.log.table.TableChange.Companion.MAX_STRING_LENGTH import com.google.common.truth.Truth.assertThat import junit.framework.Assert.assertTrue import org.junit.Test @SmallTest Loading Loading @@ -326,4 +328,152 @@ class TableChangeTest : SysuiTestCase() { assertThat(underTest.getVal()).doesNotContain(IS_INITIAL_PREFIX) } @Test fun constructor_columnAndValueTooLong_truncated() { val underTest = TableChange( columnPrefix = "P".repeat(MAX_STRING_LENGTH + 10), columnName = "N".repeat(MAX_STRING_LENGTH + 10), type = TableChange.DataType.STRING, str = "V".repeat(MAX_STRING_LENGTH + 10), ) assertThat(underTest.getName()).contains("P".repeat(MAX_STRING_LENGTH)) assertThat(underTest.getName()).doesNotContain("P".repeat(MAX_STRING_LENGTH + 1)) assertThat(underTest.getName()).contains("N".repeat(MAX_STRING_LENGTH)) assertThat(underTest.getName()).doesNotContain("N".repeat(MAX_STRING_LENGTH + 1)) assertThat(underTest.getVal()).isEqualTo("V".repeat(MAX_STRING_LENGTH)) } @Test fun constructor_columnNameNotTooLong_noReallocation() { val inputColumnName = "fakeName" val inputValue = "fakeValue" val underTest = TableChange( columnPrefix = "", columnName = inputColumnName, type = TableChange.DataType.STRING, str = inputValue, ) // Use referential equality to verify we didn't reallocate a new string when the string is // *not* too long. assertTrue(underTest.getColumnName() === inputColumnName) } @Test fun reset_columnPrefixTooLong_truncated() { val underTest = TableChange() underTest.reset( timestamp = 1L, columnPrefix = "P".repeat(MAX_STRING_LENGTH + 10), columnName = "name", isInitial = false, ) assertThat(underTest.getName()).contains("P".repeat(MAX_STRING_LENGTH)) assertThat(underTest.getName()).doesNotContain("P".repeat(MAX_STRING_LENGTH + 1)) } @Test fun reset_columnNameTooLong_truncated() { val underTest = TableChange() underTest.reset( timestamp = 1L, columnPrefix = "prefix", columnName = "N".repeat(MAX_STRING_LENGTH + 10), isInitial = false, ) assertThat(underTest.getName()).contains("N".repeat(MAX_STRING_LENGTH)) assertThat(underTest.getName()).doesNotContain("N".repeat(MAX_STRING_LENGTH + 1)) } @Test fun reset_columnNameNotTooLong_noReallocation() { val underTest = TableChange() val shortColumnName = "shortColumnName" underTest.reset( timestamp = 1L, columnPrefix = "prefix", columnName = shortColumnName, isInitial = false, ) // Use referential equality to verify we didn't reallocate a new string when the string is // *not* too long. assertTrue(underTest.getColumnName() === shortColumnName) } @Test fun setString_valueTooLong_truncated() { val underTest = TableChange() underTest.set("V".repeat(MAX_STRING_LENGTH + 1)) assertThat(underTest.getVal()).isEqualTo("V".repeat(MAX_STRING_LENGTH)) } @Test fun updateTo_newColumnPrefixTooLong_truncated() { val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName") underTest.set(42) val new = TableChange( columnPrefix = "P".repeat(MAX_STRING_LENGTH + 10), columnName = "name", ) underTest.updateTo(new) assertThat(underTest.getName()).contains("P".repeat(MAX_STRING_LENGTH)) assertThat(underTest.getName()).doesNotContain("P".repeat(MAX_STRING_LENGTH + 1)) } @Test fun updateTo_newColumnNameTooLong_truncated() { val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName") underTest.set(42) val new = TableChange( columnPrefix = "prefix", columnName = "N".repeat(MAX_STRING_LENGTH + 10), ) underTest.updateTo(new) assertThat(underTest.getName()).contains("N".repeat(MAX_STRING_LENGTH)) assertThat(underTest.getName()).doesNotContain("N".repeat(MAX_STRING_LENGTH + 1)) } @Test fun updateTo_columnNameNotTooLong_noReallocation() { val underTest = TableChange() val shortColumnName = "shortColumnName" val new = TableChange(columnPrefix = "prefix", columnName = shortColumnName) underTest.updateTo(new) // Use referential equality to verify we didn't reallocate a new string when the string is // *not* too long. assertTrue(underTest.getColumnName() === shortColumnName) } @Test fun updateTo_newValTooLong_truncated() { val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName") underTest.set("value") val new = TableChange() new.set("V".repeat(MAX_STRING_LENGTH + 10)) underTest.updateTo(new) assertThat(underTest.getVal()).isEqualTo("V".repeat(MAX_STRING_LENGTH)) } }
packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt +107 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,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.log.table.TableChange.Companion.MAX_STRING_LENGTH import com.android.systemui.plugins.log.LogLevel import com.android.systemui.plugins.log.LogcatEchoTracker import com.android.systemui.util.mockito.any Loading Loading @@ -575,6 +576,112 @@ class TableLogBufferTest : SysuiTestCase() { assertThat(dumpedString).contains(expected6) } @Test fun dumpChanges_tooLongColumnPrefix_viaLogChange_truncated() { underTest.logChange( prefix = "P".repeat(MAX_STRING_LENGTH + 10), columnName = "name", value = true, ) val dumpedString = dumpChanges() assertThat(dumpedString).contains("P".repeat(MAX_STRING_LENGTH)) assertThat(dumpedString).doesNotContain("P".repeat(MAX_STRING_LENGTH + 1)) } @Test fun dumpChanges_tooLongColumnPrefix_viaLogDiffs_truncated() { val prevDiffable = object : TestDiffable() {} val nextDiffable = object : TestDiffable() { override fun logDiffs(prevVal: TestDiffable, row: TableRowLogger) { row.logChange("status", "value") } } // WHEN the column prefix is too large underTest.logDiffs( columnPrefix = "P".repeat(MAX_STRING_LENGTH + 10), prevDiffable, nextDiffable, ) val dumpedString = dumpChanges() // THEN it's truncated to the max length assertThat(dumpedString).contains("P".repeat(MAX_STRING_LENGTH)) assertThat(dumpedString).doesNotContain("P".repeat(MAX_STRING_LENGTH + 1)) } @Test fun dumpChanges_tooLongColumnName_viaLogChange_truncated() { underTest.logChange( prefix = "prefix", columnName = "N".repeat(MAX_STRING_LENGTH + 10), value = 10, ) val dumpedString = dumpChanges() assertThat(dumpedString).contains("N".repeat(MAX_STRING_LENGTH)) assertThat(dumpedString).doesNotContain("N".repeat(MAX_STRING_LENGTH + 1)) } @Test fun dumpChanges_tooLongColumnName_viaLogDiffs_truncated() { val prevDiffable = object : TestDiffable() {} val nextDiffable = object : TestDiffable() { override fun logDiffs(prevVal: TestDiffable, row: TableRowLogger) { // WHEN the column name is too large row.logChange(columnName = "N".repeat(MAX_STRING_LENGTH + 10), "value") } } underTest.logDiffs(columnPrefix = "prefix", prevDiffable, nextDiffable) val dumpedString = dumpChanges() // THEN it's truncated to the max length assertThat(dumpedString).contains("N".repeat(MAX_STRING_LENGTH)) assertThat(dumpedString).doesNotContain("N".repeat(MAX_STRING_LENGTH + 1)) } @Test fun dumpChanges_tooLongValue_viaLogChange_truncated() { underTest.logChange( prefix = "prefix", columnName = "name", value = "V".repeat(MAX_STRING_LENGTH + 10), ) val dumpedString = dumpChanges() assertThat(dumpedString).contains("V".repeat(MAX_STRING_LENGTH)) assertThat(dumpedString).doesNotContain("V".repeat(MAX_STRING_LENGTH + 1)) } @Test fun dumpChanges_tooLongValue_viaLogDiffs_truncated() { val prevDiffable = object : TestDiffable() {} val nextDiffable = object : TestDiffable() { override fun logDiffs(prevVal: TestDiffable, row: TableRowLogger) { // WHEN the value is too large row.logChange("columnName", value = "V".repeat(MAX_STRING_LENGTH + 10)) } } underTest.logDiffs(columnPrefix = "prefix", prevDiffable, nextDiffable) val dumpedString = dumpChanges() // THEN it's truncated to the max length assertThat(dumpedString).contains("V".repeat(MAX_STRING_LENGTH)) assertThat(dumpedString).doesNotContain("V".repeat(MAX_STRING_LENGTH + 1)) } @Test fun dumpChanges_rotatesIfBufferIsFull() { lateinit var valToDump: String Loading