Skip to content

Commit

Permalink
Check Window flags when selecting root view in LocalUiController. #6741
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 399115715
  • Loading branch information
Googler authored and copybara-robolectric committed Sep 29, 2021
1 parent 1eae515 commit 52cc2fd
Show file tree
Hide file tree
Showing 27 changed files with 166 additions and 314 deletions.
214 changes: 0 additions & 214 deletions .circleci/config.yml

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Expand Up @@ -29,7 +29,7 @@ jobs:
java-version: 11.0.8

- name: Build
run: SKIP_JAVADOC=true ./gradlew clean assemble testClasses --parallel --stacktrace
run: SKIP_ERRORPRONE=true SKIP_JAVADOC=true ./gradlew clean assemble testClasses --parallel --stacktrace

tests:
runs-on: ubuntu-18.04
Expand Down Expand Up @@ -58,7 +58,7 @@ jobs:

- name: Run tests
run: |
./gradlew test --info --stacktrace --continue \
SKIP_ERRORPRONE=true SKIP_JAVADOC=true ./gradlew test --info --stacktrace --continue \
--parallel \
-Drobolectric.enabledSdks=${{ matrix.api-versions }} \
-Drobolectric.alwaysIncludeVariantMarkersInTestName=true \
Expand Down
3 changes: 1 addition & 2 deletions README.md
@@ -1,6 +1,5 @@
<a name="README">[<img src="https://rawgithub.com/robolectric/robolectric/master/images/robolectric-horizontal.png"/>](http://robolectric.org)</a>

[![Build Status](https://circleci.com/gh/robolectric/robolectric.svg?style=svg)](https://circleci.com/gh/robolectric/robolectric)
[![Build Status](https://github.com/robolectric/robolectric/actions/workflows/tests.yml/badge.svg)](https://github.com/robolectric/robolectric/actions?query=workflow%3Atests)
[![GitHub release](https://img.shields.io/github/release/robolectric/robolectric.svg?maxAge=60)](https://github.com/robolectric/robolectric/releases)

Robolectric is the industry-standard unit testing framework for Android. With Robolectric, your tests run in a simulated Android environment inside a JVM, without the overhead of an emulator.
Expand Down
Expand Up @@ -8,18 +8,21 @@ import org.gradle.api.tasks.compile.JavaCompile
class RoboJavaModulePlugin implements Plugin<Project> {
Closure doApply = {
apply plugin: "java-library"
apply plugin: "net.ltgt.errorprone"

def skipErrorprone = System.getenv('SKIP_ERRORPRONE') == "true"
if (!skipErrorprone) {
apply plugin: "net.ltgt.errorprone"
project.dependencies {
errorprone("com.google.errorprone:error_prone_core:$errorproneVersion")
errorproneJavac("com.google.errorprone:javac:$errorproneJavacVersion")
}
}

apply plugin: AarDepsPlugin

sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8

project.dependencies {
errorprone("com.google.errorprone:error_prone_core:$errorproneVersion")
errorproneJavac("com.google.errorprone:javac:$errorproneJavacVersion")
}

tasks.withType(JavaCompile) { task ->
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
Expand Down
Expand Up @@ -1032,7 +1032,6 @@ int register_android_database_SQLiteConnection(JNIEnv* env) {
return JNI_ERR;
}

printf("found SQLiteConnectionNatives!\n");
jclass unaryClazz = env->FindClass("java/util/function/UnaryOperator");
gUnaryOperator.apply = env->GetMethodID(
unaryClazz, "apply", "(Ljava/lang/Object;)Ljava/lang/Object;");
Expand Down
Expand Up @@ -600,7 +600,7 @@ private static final class UnExecutedRunnablesException extends Exception {
super(
"Main looper has queued unexecuted runnables. "
+ "This might be the cause of the test failure. "
+ "You might need a shadowOf(getMainLooper()).idle() call.");
+ "You might need a shadowOf(Looper.getMainLooper()).idle() call.");
}

@Override
Expand Down
Expand Up @@ -38,7 +38,8 @@ public boolean injectMotionEvent(MotionEvent event) throws InjectEventSecurityEx
checkState(Looper.myLooper() == Looper.getMainLooper(), "Expecting to be on main thread!");
loopMainThreadUntilIdle();

getViewRoot().dispatchTouchEvent(event);
// FLAG_NOT_TOUCHABLE: "this window can never receive touch events"
getTopMostViewRootExcluding(LayoutParams.FLAG_NOT_TOUCHABLE).dispatchTouchEvent(event);

loopMainThreadUntilIdle();

Expand All @@ -49,9 +50,10 @@ public boolean injectMotionEvent(MotionEvent event) throws InjectEventSecurityEx
public boolean injectKeyEvent(KeyEvent event) throws InjectEventSecurityException {
checkNotNull(event);
checkState(Looper.myLooper() == Looper.getMainLooper(), "Expecting to be on main thread!");

loopMainThreadUntilIdle();
getViewRoot().dispatchKeyEvent(event);

// FLAG_NOT_FOCUSABLE: "this window won't ever get key input focus"
getTopMostViewRootExcluding(LayoutParams.FLAG_NOT_FOCUSABLE).dispatchKeyEvent(event);

loopMainThreadUntilIdle();
return true;
Expand Down Expand Up @@ -146,7 +148,7 @@ public void loopMainThreadForAtLeast(long millisDelay) {
shadowMainLooper().idleFor(Duration.ofMillis(millisDelay));
}

private View getViewRoot() {
private View getTopMostViewRootExcluding(int prohibitedFlags) {
List<ViewRootImpl> viewRoots = getViewRoots();
if (viewRoots.isEmpty()) {
throw new IllegalStateException("no view roots!");
Expand All @@ -159,9 +161,13 @@ private View getViewRoot() {
int topMostRootIndex = 0;
for (int i = 0; i < params.size(); i++) {
LayoutParams param = params.get(i);
if (param.type > params.get(topMostRootIndex).type) {
topMostRootIndex = i;
if ((param.flags & prohibitedFlags) != 0) {
continue;
}
if (param.type <= params.get(topMostRootIndex).type) {
continue;
}
topMostRootIndex = i;
}
return viewRoots.get(topMostRootIndex).getView();
}
Expand Down
Expand Up @@ -290,8 +290,9 @@ public void shouldDiagnoseUnexecutedRunnables() throws Exception {
"finished: failWithNoRunnables",
"started: failWithUnexecutedRunnables",
"failure: failing with unexecuted runnable\n"
+ "Suppressed: Main looper has queued unexecuted runnables. This might be the cause"
+ " of the test failure. You might need a shadowOf(getMainLooper()).idle() call.",
+ "Suppressed: Main looper has queued unexecuted runnables. "
+ "This might be the cause of the test failure. "
+ "You might need a shadowOf(Looper.getMainLooper()).idle() call.",
"finished: failWithUnexecutedRunnables",
"started: assumptionViolationWithNoRunnables",
"ignored: assumptionViolationWithNoRunnables: assumption violated",
Expand Down
Expand Up @@ -14,6 +14,7 @@
import java.net.Socket;
import java.time.Duration;
import java.util.Arrays;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -36,19 +37,27 @@ public void systemLog_shouldWriteToStderr() throws Throwable {
try {
for (String methodName : new String[] {"logE", "logW"}) {
stream.reset();
// One parameter: [message]
invokeDynamic(
System.class, methodName, void.class, ClassParameter.from(String.class, "hello"));
String expected1 = String.format("System\\.%s: hello", methodName);
// Two parameters: [message, throwable]
// We verify that the stack trace is dumped by looking for the name of this method.
invokeDynamic(
System.class,
methodName,
void.class,
ClassParameter.from(String.class, "world"),
ClassParameter.from(Throwable.class, new Throwable("throw")));
ClassParameter.from(Throwable.class, new Throwable("message")));
String expected2 =
String.format(
"System.%s: world.*java\\.lang\\.Throwable: message.*"
+ "at .*AndroidInterceptorsIntegrationTest\\.systemLog_shouldWriteToStderr",
methodName);
// Due to the possibility of running tests in Parallel, assertions checking stderr contents
// should not assert equality.
assertThat(stream.toString().split("\\r?\\n")).asList().containsAtLeast(String.format(
"System.%s: hello", methodName), String.format(
"System.%s: worldjava.lang.Throwable: throw", methodName)).inOrder();
assertThat(stream.toString())
.matches(Pattern.compile(".*" + expected1 + ".*" + expected2 + ".*", Pattern.DOTALL));
}
} finally {
System.setErr(stderr);
Expand Down
Expand Up @@ -52,4 +52,11 @@ public void testSetTitle() {
shadow.setTitle(title);
assertThat(shadow.getTitle().toString()).isEqualTo(title.toString());
}

@Test
public void testSetChild() {
AccessibilityWindowInfo window = AccessibilityWindowInfo.obtain();
shadow.addChild(window);
assertThat(shadow.getChild(0)).isEqualTo(window);
}
}

0 comments on commit 52cc2fd

Please sign in to comment.