@ -7,7 +7,9 @@ package org.mozilla.fenix.ui
import android.util.Log
import android.util.Log
import android.view.View
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.children
import androidx.core.view.children
import androidx.recyclerview.widget.RecyclerView
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiDevice
import kotlinx.android.synthetic.main.activity_home.*
import kotlinx.android.synthetic.main.activity_home.*
@ -24,6 +26,7 @@ private const val EXPECTED_SUPPRESSION_COUNT = 11
private const val EXPECTED _RUNBLOCKING _COUNT = 2
private const val EXPECTED _RUNBLOCKING _COUNT = 2
private const val EXPECTED _COMPONENT _INIT _COUNT = 42
private const val EXPECTED _COMPONENT _INIT _COUNT = 42
private const val EXPECTED _VIEW _HIERARCHY _DEPTH = 12
private const val EXPECTED _VIEW _HIERARCHY _DEPTH = 12
private const val EXPECTED _RECYCLER _VIEW _CONSTRAINT _LAYOUT _CHILDREN = 4
private val failureMsgStrictMode = getErrorMessage (
private val failureMsgStrictMode = getErrorMessage (
shortName = " StrictMode suppression " ,
shortName = " StrictMode suppression " ,
@ -46,6 +49,13 @@ private val failureMsgViewHierarchyDepth = getErrorMessage(
) + " Please note that we're not sure if this is a useful metric to assert: with your feedback, " +
) + " Please note that we're not sure if this is a useful metric to assert: with your feedback, " +
" we'll find out over time if it is or is not. "
" we'll find out over time if it is or is not. "
private val failureMsgRecyclerViewConstraintLayoutChildren = getErrorMessage (
shortName = " ConstraintLayout being a common direct descendant of a RecyclerView " ,
implications = " ConstraintLayouts are slow to inflate and are primarily used to flatten deep " +
" view hierarchies so can be under-performant as a common RecyclerView child? "
) + " Please note that we're not sure if this is a useful metric to assert: with your feedback, " +
" we'll find out over time if it is or is not. "
/ * *
/ * *
* A performance test to limit the number of StrictMode suppressions and number of runBlocking used
* A performance test to limit the number of StrictMode suppressions and number of runBlocking used
* on startup .
* on startup .
@ -79,12 +89,20 @@ class StartupExcessiveResourceUseTest {
val actualSuppresionCount = activityTestRule . activity . components . strictMode . suppressionCount . get ( ) . toInt ( )
val actualSuppresionCount = activityTestRule . activity . components . strictMode . suppressionCount . get ( ) . toInt ( )
val actualRunBlocking = RunBlockingCounter . count . get ( )
val actualRunBlocking = RunBlockingCounter . count . get ( )
val actualComponentInitCount = ComponentInitCount . count . get ( )
val actualComponentInitCount = ComponentInitCount . count . get ( )
val actualViewHierarchyDepth = countAndLogViewHierarchyDepth ( activityTestRule . activity . rootContainer , 1 )
val rootView = activityTestRule . activity . rootContainer
val actualViewHierarchyDepth = countAndLogViewHierarchyDepth ( rootView , 1 )
val actualRecyclerViewConstraintLayoutChildren = countRecyclerViewConstraintLayoutChildren ( rootView , null )
assertEquals ( failureMsgStrictMode , EXPECTED _SUPPRESSION _COUNT , actualSuppresionCount )
assertEquals ( failureMsgStrictMode , EXPECTED _SUPPRESSION _COUNT , actualSuppresionCount )
assertEquals ( failureMsgRunBlocking , EXPECTED _RUNBLOCKING _COUNT , actualRunBlocking )
assertEquals ( failureMsgRunBlocking , EXPECTED _RUNBLOCKING _COUNT , actualRunBlocking )
assertEquals ( failureMsgComponentInit , EXPECTED _COMPONENT _INIT _COUNT , actualComponentInitCount )
assertEquals ( failureMsgComponentInit , EXPECTED _COMPONENT _INIT _COUNT , actualComponentInitCount )
assertEquals ( failureMsgViewHierarchyDepth , EXPECTED _VIEW _HIERARCHY _DEPTH , actualViewHierarchyDepth )
assertEquals ( failureMsgViewHierarchyDepth , EXPECTED _VIEW _HIERARCHY _DEPTH , actualViewHierarchyDepth )
assertEquals (
failureMsgRecyclerViewConstraintLayoutChildren ,
EXPECTED _RECYCLER _VIEW _CONSTRAINT _LAYOUT _CHILDREN ,
actualRecyclerViewConstraintLayoutChildren
)
}
}
}
}
@ -101,6 +119,20 @@ private fun countAndLogViewHierarchyDepth(view: View, level: Int): Int {
}
}
}
}
private fun countRecyclerViewConstraintLayoutChildren ( view : View , parent : View ? ) : Int {
val viewValue = if ( parent is RecyclerView && view is ConstraintLayout ) {
1
} else {
0
}
return if ( view !is ViewGroup ) {
viewValue
} else {
viewValue + view . children . sumBy { countRecyclerViewConstraintLayoutChildren ( it , view ) }
}
}
private fun getErrorMessage ( shortName : String , implications : String ) = """ $shortName count does not match expected count.
private fun getErrorMessage ( shortName : String , implications : String ) = """ $shortName count does not match expected count.
If this PR removed a $ shortName call , great ! Please decrease the count .
If this PR removed a $ shortName call , great ! Please decrease the count .