Bug 1927595 - Open GeckoViewTest Priority Tests for Isolated Processes r=geckoview-reviewers,m_kato
Issue was `getContentProcessesOomScore` was attempting to read other process's oom scores. This patch: * Adjusts `getContentProcessesOomScore` to read the oom score through the test privileged `uiAutomation` * Opens tests in `GeckoViewTest` gated by isolated process * Runs ktlint on `GeckoViewTest` Differential Revision: https://phabricator.services.mozilla.com/D246355
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
@file:Suppress("ktlint:standard:no-wildcard-imports")
|
||||||
|
|
||||||
package org.mozilla.geckoview.test
|
package org.mozilla.geckoview.test
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@@ -5,6 +7,7 @@ import android.graphics.Matrix
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.LocaleList
|
import android.os.LocaleList
|
||||||
|
import android.os.ParcelFileDescriptor
|
||||||
import android.util.Pair
|
import android.util.Pair
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -15,11 +18,11 @@ import androidx.test.ext.junit.rules.ActivityScenarioRule
|
|||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.LargeTest
|
import androidx.test.filters.LargeTest
|
||||||
import androidx.test.filters.SdkSuppress
|
import androidx.test.filters.SdkSuppress
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import org.hamcrest.Matchers.equalTo
|
import org.hamcrest.Matchers.equalTo
|
||||||
import org.junit.* // ktlint-disable no-wildcard-imports
|
import org.junit.*
|
||||||
import org.junit.Assert.assertFalse
|
import org.junit.Assert.assertFalse
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
import org.junit.Assume.assumeThat
|
|
||||||
import org.junit.rules.RuleChain
|
import org.junit.rules.RuleChain
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mozilla.geckoview.Autofill
|
import org.mozilla.geckoview.Autofill
|
||||||
@@ -27,12 +30,12 @@ import org.mozilla.geckoview.GeckoSession
|
|||||||
import org.mozilla.geckoview.GeckoView
|
import org.mozilla.geckoview.GeckoView
|
||||||
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.NullDelegate
|
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.NullDelegate
|
||||||
import org.mozilla.geckoview.test.util.UiThreadUtils
|
import org.mozilla.geckoview.test.util.UiThreadUtils
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@LargeTest
|
@LargeTest
|
||||||
class GeckoViewTest : BaseSessionTest() {
|
class GeckoViewTest : BaseSessionTest() {
|
||||||
val activityRule = ActivityScenarioRule(GeckoViewTestActivity::class.java)
|
val activityRule = ActivityScenarioRule(GeckoViewTestActivity::class.java)
|
||||||
|
private val uiAutomation = InstrumentationRegistry.getInstrumentation().uiAutomation
|
||||||
|
|
||||||
@get:Rule
|
@get:Rule
|
||||||
override val rules = RuleChain.outerRule(activityRule).around(sessionRule)
|
override val rules = RuleChain.outerRule(activityRule).around(sessionRule)
|
||||||
@@ -95,13 +98,19 @@ class GeckoViewTest : BaseSessionTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun waitUntilContentProcessPriority(high: List<GeckoSession>, low: List<GeckoSession>) {
|
private fun waitUntilContentProcessPriority(
|
||||||
|
high: List<GeckoSession>,
|
||||||
|
low: List<GeckoSession>,
|
||||||
|
) {
|
||||||
val highPids = high.map { sessionRule.getSessionPid(it) }.toSet()
|
val highPids = high.map { sessionRule.getSessionPid(it) }.toSet()
|
||||||
val lowPids = low.map { sessionRule.getSessionPid(it) }.toSet()
|
val lowPids = low.map { sessionRule.getSessionPid(it) }.toSet()
|
||||||
waitUntilContentProcessPriorityByPid(highPids = highPids, lowPids = lowPids)
|
waitUntilContentProcessPriorityByPid(highPids = highPids, lowPids = lowPids)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun waitUntilContentProcessPriorityByPid(highPids: Collection<Int>, lowPids: Collection<Int>) {
|
private fun waitUntilContentProcessPriorityByPid(
|
||||||
|
highPids: Collection<Int>,
|
||||||
|
lowPids: Collection<Int>,
|
||||||
|
) {
|
||||||
UiThreadUtils.waitForCondition({
|
UiThreadUtils.waitForCondition({
|
||||||
val shouldBeHighPri = getContentProcessesOomScore(highPids)
|
val shouldBeHighPri = getContentProcessesOomScore(highPids)
|
||||||
val shouldBeLowPri = getContentProcessesOomScore(lowPids)
|
val shouldBeLowPri = getContentProcessesOomScore(lowPids)
|
||||||
@@ -111,11 +120,17 @@ class GeckoViewTest : BaseSessionTest() {
|
|||||||
}, env.defaultTimeoutMillis)
|
}, env.defaultTimeoutMillis)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getContentProcessesOomScore(pids: Collection<Int>): List<Int> {
|
fun getContentProcessesOomScore(pids: Collection<Int>): List<Int> =
|
||||||
return pids.map { pid ->
|
pids.map { pid ->
|
||||||
File("/proc/$pid/oom_score").readText(Charsets.UTF_8).trim().toInt()
|
val shellCommand = uiAutomation.executeShellCommand("cat /proc/$pid/oom_score")
|
||||||
|
ParcelFileDescriptor.AutoCloseInputStream(shellCommand).use { inputStream ->
|
||||||
|
inputStream
|
||||||
|
.bufferedReader(Charsets.UTF_8)
|
||||||
|
.readText()
|
||||||
|
.trim()
|
||||||
|
.toInt()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun setupPriorityTest(): GeckoSession {
|
fun setupPriorityTest(): GeckoSession {
|
||||||
// This makes the test a little bit faster
|
// This makes the test a little bit faster
|
||||||
@@ -152,8 +167,6 @@ class GeckoViewTest : BaseSessionTest() {
|
|||||||
@Test
|
@Test
|
||||||
@NullDelegate(Autofill.Delegate::class)
|
@NullDelegate(Autofill.Delegate::class)
|
||||||
fun setTabActiveKeepsTabAtHighPriority() {
|
fun setTabActiveKeepsTabAtHighPriority() {
|
||||||
// Bug 1927595
|
|
||||||
assumeThat(env.isIsolatedProcess, equalTo(false))
|
|
||||||
activityRule.scenario.onActivity {
|
activityRule.scenario.onActivity {
|
||||||
val otherSession = setupPriorityTest()
|
val otherSession = setupPriorityTest()
|
||||||
|
|
||||||
@@ -180,8 +193,6 @@ class GeckoViewTest : BaseSessionTest() {
|
|||||||
@Test
|
@Test
|
||||||
@NullDelegate(Autofill.Delegate::class)
|
@NullDelegate(Autofill.Delegate::class)
|
||||||
fun processPriorityTest() {
|
fun processPriorityTest() {
|
||||||
// Bug 1927595
|
|
||||||
assumeThat(env.isIsolatedProcess, equalTo(false))
|
|
||||||
activityRule.scenario.onActivity {
|
activityRule.scenario.onActivity {
|
||||||
val otherSession = setupPriorityTest()
|
val otherSession = setupPriorityTest()
|
||||||
|
|
||||||
@@ -221,8 +232,6 @@ class GeckoViewTest : BaseSessionTest() {
|
|||||||
@Test
|
@Test
|
||||||
@NullDelegate(Autofill.Delegate::class)
|
@NullDelegate(Autofill.Delegate::class)
|
||||||
fun setPriorityHint() {
|
fun setPriorityHint() {
|
||||||
// Bug 1927595
|
|
||||||
assumeThat(env.isIsolatedProcess, equalTo(false))
|
|
||||||
val otherSession = setupPriorityTest()
|
val otherSession = setupPriorityTest()
|
||||||
|
|
||||||
// Setting priorityHint to PRIORITY_HIGH raises priority
|
// Setting priorityHint to PRIORITY_HIGH raises priority
|
||||||
@@ -245,9 +254,6 @@ class GeckoViewTest : BaseSessionTest() {
|
|||||||
@Test
|
@Test
|
||||||
@NullDelegate(Autofill.Delegate::class)
|
@NullDelegate(Autofill.Delegate::class)
|
||||||
fun setActiveProcessPriorityTest() {
|
fun setActiveProcessPriorityTest() {
|
||||||
// Bug 1927595
|
|
||||||
assumeThat(env.isIsolatedProcess, equalTo(false))
|
|
||||||
|
|
||||||
sessionRule.setPrefsUntilTestEnd(
|
sessionRule.setPrefsUntilTestEnd(
|
||||||
mapOf(
|
mapOf(
|
||||||
"dom.ipc.processPriorityManager.backgroundGracePeriodMS" to 0,
|
"dom.ipc.processPriorityManager.backgroundGracePeriodMS" to 0,
|
||||||
@@ -295,7 +301,10 @@ class GeckoViewTest : BaseSessionTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun visit(node: MockViewStructure, callback: (MockViewStructure) -> Unit) {
|
private fun visit(
|
||||||
|
node: MockViewStructure,
|
||||||
|
callback: (MockViewStructure) -> Unit,
|
||||||
|
) {
|
||||||
callback(node)
|
callback(node)
|
||||||
|
|
||||||
for (child in node.children) {
|
for (child in node.children) {
|
||||||
@@ -312,22 +321,24 @@ class GeckoViewTest : BaseSessionTest() {
|
|||||||
mainSession.loadTestPath(FORMS_XORIGIN_HTML_PATH)
|
mainSession.loadTestPath(FORMS_XORIGIN_HTML_PATH)
|
||||||
mainSession.waitForPageStop()
|
mainSession.waitForPageStop()
|
||||||
|
|
||||||
val autofills = mapOf(
|
val autofills =
|
||||||
"#user1" to "username@example.com",
|
mapOf(
|
||||||
"#user2" to "username@example.com",
|
"#user1" to "username@example.com",
|
||||||
"#pass1" to "test-password",
|
"#user2" to "username@example.com",
|
||||||
"#pass2" to "test-password",
|
"#pass1" to "test-password",
|
||||||
)
|
"#pass2" to "test-password",
|
||||||
|
)
|
||||||
|
|
||||||
// Set up promises to monitor the values changing.
|
// Set up promises to monitor the values changing.
|
||||||
val promises = autofills.map { entry ->
|
val promises =
|
||||||
// Repeat each test with both the top document and the iframe document.
|
autofills.map { entry ->
|
||||||
mainSession.evaluatePromiseJS(
|
// Repeat each test with both the top document and the iframe document.
|
||||||
"""
|
mainSession.evaluatePromiseJS(
|
||||||
|
"""
|
||||||
window.getDataForAllFrames('${entry.key}', '${entry.value}')
|
window.getDataForAllFrames('${entry.key}', '${entry.value}')
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
activityRule.scenario.onActivity {
|
activityRule.scenario.onActivity {
|
||||||
val root = MockViewStructure(View.NO_ID)
|
val root = MockViewStructure(View.NO_ID)
|
||||||
@@ -385,14 +396,22 @@ class GeckoViewTest : BaseSessionTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockViewStructure(var id: Int, var parent: MockViewStructure? = null) : ViewStructure() {
|
class MockViewStructure(
|
||||||
|
var id: Int,
|
||||||
|
var parent: MockViewStructure? = null,
|
||||||
|
) : ViewStructure() {
|
||||||
private var enabled: Boolean = false
|
private var enabled: Boolean = false
|
||||||
private var inputType = 0
|
private var inputType = 0
|
||||||
var children = Array<MockViewStructure?>(0, { null })
|
var children = Array<MockViewStructure?>(0, { null })
|
||||||
var childIndex = 0
|
var childIndex = 0
|
||||||
var hints: Array<out String>? = null
|
var hints: Array<out String>? = null
|
||||||
|
|
||||||
override fun setId(p0: Int, p1: String?, p2: String?, p3: String?) {
|
override fun setId(
|
||||||
|
p0: Int,
|
||||||
|
p1: String?,
|
||||||
|
p2: String?,
|
||||||
|
p3: String?,
|
||||||
|
) {
|
||||||
id = p0
|
id = p0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,9 +423,7 @@ class GeckoViewTest : BaseSessionTest() {
|
|||||||
children = Array(p0, { null })
|
children = Array(p0, { null })
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getChildCount(): Int {
|
override fun getChildCount(): Int = children.size
|
||||||
return children.size
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun newChild(p0: Int): ViewStructure {
|
override fun newChild(p0: Int): ViewStructure {
|
||||||
val child = MockViewStructure(p0, this)
|
val child = MockViewStructure(p0, this)
|
||||||
@@ -414,17 +431,13 @@ class GeckoViewTest : BaseSessionTest() {
|
|||||||
return child
|
return child
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun asyncNewChild(p0: Int): ViewStructure {
|
override fun asyncNewChild(p0: Int): ViewStructure = newChild(p0)
|
||||||
return newChild(p0)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setInputType(p0: Int) {
|
override fun setInputType(p0: Int) {
|
||||||
inputType = p0
|
inputType = p0
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getInputType(): Int {
|
fun getInputType(): Int = inputType
|
||||||
return inputType
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setAutofillHints(p0: Array<out String>?) {
|
override fun setAutofillHints(p0: Array<out String>?) {
|
||||||
hints = p0
|
hints = p0
|
||||||
@@ -434,76 +447,119 @@ class GeckoViewTest : BaseSessionTest() {
|
|||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setDimens(p0: Int, p1: Int, p2: Int, p3: Int, p4: Int, p5: Int) {}
|
override fun setDimens(
|
||||||
override fun setTransformation(p0: Matrix?) {}
|
p0: Int,
|
||||||
override fun setElevation(p0: Float) {}
|
p1: Int,
|
||||||
override fun setAlpha(p0: Float) {}
|
p2: Int,
|
||||||
override fun setVisibility(p0: Int) {}
|
p3: Int,
|
||||||
override fun setClickable(p0: Boolean) {}
|
p4: Int,
|
||||||
override fun setLongClickable(p0: Boolean) {}
|
p5: Int,
|
||||||
override fun setContextClickable(p0: Boolean) {}
|
) {}
|
||||||
override fun setFocusable(p0: Boolean) {}
|
|
||||||
override fun setFocused(p0: Boolean) {}
|
override fun setTransformation(p0: Matrix?) {}
|
||||||
override fun setAccessibilityFocused(p0: Boolean) {}
|
|
||||||
override fun setCheckable(p0: Boolean) {}
|
override fun setElevation(p0: Float) {}
|
||||||
override fun setChecked(p0: Boolean) {}
|
|
||||||
override fun setSelected(p0: Boolean) {}
|
override fun setAlpha(p0: Float) {}
|
||||||
override fun setActivated(p0: Boolean) {}
|
|
||||||
override fun setOpaque(p0: Boolean) {}
|
override fun setVisibility(p0: Int) {}
|
||||||
override fun setClassName(p0: String?) {}
|
|
||||||
override fun setContentDescription(p0: CharSequence?) {}
|
override fun setClickable(p0: Boolean) {}
|
||||||
override fun setText(p0: CharSequence?) {}
|
|
||||||
override fun setText(p0: CharSequence?, p1: Int, p2: Int) {}
|
override fun setLongClickable(p0: Boolean) {}
|
||||||
override fun setTextStyle(p0: Float, p1: Int, p2: Int, p3: Int) {}
|
|
||||||
override fun setTextLines(p0: IntArray?, p1: IntArray?) {}
|
override fun setContextClickable(p0: Boolean) {}
|
||||||
override fun setHint(p0: CharSequence?) {}
|
|
||||||
override fun getText(): CharSequence {
|
override fun setFocusable(p0: Boolean) {}
|
||||||
return ""
|
|
||||||
}
|
override fun setFocused(p0: Boolean) {}
|
||||||
override fun getTextSelectionStart(): Int {
|
|
||||||
return 0
|
override fun setAccessibilityFocused(p0: Boolean) {}
|
||||||
}
|
|
||||||
override fun getTextSelectionEnd(): Int {
|
override fun setCheckable(p0: Boolean) {}
|
||||||
return 0
|
|
||||||
}
|
override fun setChecked(p0: Boolean) {}
|
||||||
override fun getHint(): CharSequence {
|
|
||||||
return ""
|
override fun setSelected(p0: Boolean) {}
|
||||||
}
|
|
||||||
override fun getExtras(): Bundle {
|
override fun setActivated(p0: Boolean) {}
|
||||||
return Bundle()
|
|
||||||
}
|
override fun setOpaque(p0: Boolean) {}
|
||||||
override fun hasExtras(): Boolean {
|
|
||||||
return false
|
override fun setClassName(p0: String?) {}
|
||||||
}
|
|
||||||
|
override fun setContentDescription(p0: CharSequence?) {}
|
||||||
|
|
||||||
|
override fun setText(p0: CharSequence?) {}
|
||||||
|
|
||||||
|
override fun setText(
|
||||||
|
p0: CharSequence?,
|
||||||
|
p1: Int,
|
||||||
|
p2: Int,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
override fun setTextStyle(
|
||||||
|
p0: Float,
|
||||||
|
p1: Int,
|
||||||
|
p2: Int,
|
||||||
|
p3: Int,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
override fun setTextLines(
|
||||||
|
p0: IntArray?,
|
||||||
|
p1: IntArray?,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
override fun setHint(p0: CharSequence?) {}
|
||||||
|
|
||||||
|
override fun getText(): CharSequence = ""
|
||||||
|
|
||||||
|
override fun getTextSelectionStart(): Int = 0
|
||||||
|
|
||||||
|
override fun getTextSelectionEnd(): Int = 0
|
||||||
|
|
||||||
|
override fun getHint(): CharSequence = ""
|
||||||
|
|
||||||
|
override fun getExtras(): Bundle = Bundle()
|
||||||
|
|
||||||
|
override fun hasExtras(): Boolean = false
|
||||||
|
|
||||||
|
override fun getAutofillId(): AutofillId? = null
|
||||||
|
|
||||||
override fun getAutofillId(): AutofillId? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
override fun setAutofillId(p0: AutofillId) {}
|
override fun setAutofillId(p0: AutofillId) {}
|
||||||
override fun setAutofillId(p0: AutofillId, p1: Int) {}
|
|
||||||
|
override fun setAutofillId(
|
||||||
|
p0: AutofillId,
|
||||||
|
p1: Int,
|
||||||
|
) {}
|
||||||
|
|
||||||
override fun setAutofillType(p0: Int) {}
|
override fun setAutofillType(p0: Int) {}
|
||||||
|
|
||||||
override fun setAutofillValue(p0: AutofillValue?) {}
|
override fun setAutofillValue(p0: AutofillValue?) {}
|
||||||
|
|
||||||
override fun setAutofillOptions(p0: Array<out CharSequence>?) {}
|
override fun setAutofillOptions(p0: Array<out CharSequence>?) {}
|
||||||
|
|
||||||
override fun setDataIsSensitive(p0: Boolean) {}
|
override fun setDataIsSensitive(p0: Boolean) {}
|
||||||
|
|
||||||
override fun asyncCommit() {}
|
override fun asyncCommit() {}
|
||||||
|
|
||||||
override fun setWebDomain(p0: String?) {}
|
override fun setWebDomain(p0: String?) {}
|
||||||
|
|
||||||
override fun setLocaleList(p0: LocaleList?) {}
|
override fun setLocaleList(p0: LocaleList?) {}
|
||||||
|
|
||||||
override fun newHtmlInfoBuilder(p0: String): HtmlInfo.Builder {
|
override fun newHtmlInfoBuilder(p0: String): HtmlInfo.Builder = MockHtmlInfoBuilder()
|
||||||
return MockHtmlInfoBuilder()
|
|
||||||
}
|
|
||||||
override fun setHtmlInfo(p0: HtmlInfo) {
|
override fun setHtmlInfo(p0: HtmlInfo) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockHtmlInfoBuilder : ViewStructure.HtmlInfo.Builder() {
|
class MockHtmlInfoBuilder : ViewStructure.HtmlInfo.Builder() {
|
||||||
override fun addAttribute(p0: String, p1: String): ViewStructure.HtmlInfo.Builder {
|
override fun addAttribute(
|
||||||
return this
|
p0: String,
|
||||||
}
|
p1: String,
|
||||||
|
): ViewStructure.HtmlInfo.Builder = this
|
||||||
|
|
||||||
override fun build(): ViewStructure.HtmlInfo {
|
override fun build(): ViewStructure.HtmlInfo = MockHtmlInfo()
|
||||||
return MockHtmlInfo()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockHtmlInfo : ViewStructure.HtmlInfo() {
|
class MockHtmlInfo : ViewStructure.HtmlInfo() {
|
||||||
|
|||||||
Reference in New Issue
Block a user