Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b90264a5 authored by Caitlin Shkuratov's avatar Caitlin Shkuratov Committed by Automerger Merge Worker
Browse files

Merge "[Table logging] Restrict strings to a max length." into udc-dev am:...

Merge "[Table logging] Restrict strings to a max length." into udc-dev am: b32832f9 am: fdade005

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22908239



Change-Id: I3793f592c2b864fda38fb816c5623455c35ac26e
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents f4d66042 fdade005
Loading
Loading
Loading
Loading
+23 −10
Original line number Diff line number Diff line
@@ -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
@@ -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. */
@@ -89,6 +97,8 @@ data class TableChange(
        }
    }

    fun getColumnName() = columnName

    fun getVal(): String {
        val value =
            when (type) {
@@ -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
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -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())
+150 −0
Original line number Diff line number Diff line
@@ -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
@@ -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))
    }
}
+107 −0
Original line number Diff line number Diff line
@@ -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
@@ -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