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

Commit edc72f87 authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

Use matcher to check keys received in ViewRootImplTest

In this CL, we refactor the ViewRootImplTest to store all of the
received keys in the queue. This will allow richer assertions, like
ensuring that specific keys were received, and in the expected order.

At the same time, move the BlockingQueueEventVerifier into cts-input-lib
so that it can be used by other input-related tests.

Bug: 380522059
Flag: TEST_ONLY
Test: atest ViewRootImplTest
Change-Id: I11dae887ba50db1bfe4726c865d60af2dbf211b2
parent c9dec193
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ android_test {
        "frameworks-base-testutils",
        "core-test-rules", // for libcore.dalvik.system.CloseGuardSupport
        "core-tests-support",
        "cts-input-lib",
        "android-common",
        "frameworks-core-util-lib",
        "mockwebserver",
+27 −6
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@ import static android.view.flags.Flags.toolkitFrameRateBySizeReadOnly;
import static android.view.flags.Flags.toolkitFrameRateDefaultNormalReadOnly;
import static android.view.flags.Flags.toolkitFrameRateVelocityMappingReadOnly;

import static com.android.cts.input.inputeventmatchers.InputEventMatchersKt.withKeyCode;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

@@ -91,8 +93,10 @@ import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;

import com.android.compatibility.common.util.ShellIdentityUtils;
import com.android.cts.input.BlockingQueueEventVerifier;
import com.android.window.flags.Flags;

import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
@@ -101,7 +105,9 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
@@ -121,7 +127,6 @@ public class ViewRootImplTest {

    private ViewRootImpl mViewRootImpl;
    private View mView;
    private volatile boolean mKeyReceived = false;

    private static Context sContext;
    private static Instrumentation sInstrumentation = InstrumentationRegistry.getInstrumentation();
@@ -1679,16 +1684,28 @@ public class ViewRootImplTest {
        }
    }

    class KeyView extends View {
        KeyView(Context context) {
    static class InputView extends View {
        private final BlockingQueue<InputEvent> mEvents = new LinkedBlockingQueue<>();
        private final BlockingQueueEventVerifier mVerifier =
                new BlockingQueueEventVerifier(mEvents);

        InputView(Context context) {
            super(context);
        }

        @Override
        public boolean dispatchKeyEventPreIme(KeyEvent event) {
            mKeyReceived = true;
            mEvents.add(event.copy());
            return true /*handled*/;
        }

        public void assertReceivedKey(Matcher<KeyEvent> matcher) {
            mVerifier.assertReceivedKey(matcher);
        }

        public void assertNoEvents() {
            mVerifier.assertNoEvents();
        }
    }

    /**
@@ -1697,7 +1714,7 @@ public class ViewRootImplTest {
     * Next, inject an event into this view, and check whether it is received.
     */
    private void checkKeyEvent(Runnable setup, boolean shouldReceiveKey) {
        final KeyView view = new KeyView(sContext);
        final InputView view = new InputView(sContext);
        mView = view;

        attachViewToWindow(view);
@@ -1712,7 +1729,11 @@ public class ViewRootImplTest {
            mViewRootImpl.dispatchInputEvent(event);
        });
        sInstrumentation.waitForIdleSync();
        assertEquals(shouldReceiveKey, mKeyReceived);
        if (shouldReceiveKey) {
            view.assertReceivedKey(withKeyCode(KeyEvent.KEYCODE_A));
        } else {
            view.assertNoEvents();
        }
    }

    private void attachViewToWindow(View view) {
+1 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import androidx.test.platform.app.InstrumentationRegistry
import com.android.cts.input.inputeventmatchers.withDeviceId
import com.android.cts.input.inputeventmatchers.withMotionAction
import com.android.cts.input.inputeventmatchers.withSource
import com.android.cts.input.BlockingQueueEventVerifier
import com.android.server.LocalServices
import com.android.server.accessibility.magnification.MagnificationProcessor
import com.android.server.wm.WindowManagerInternal
+0 −57
Original line number Diff line number Diff line
/*
 * Copyright 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.server.accessibility

import android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS
import android.view.InputEvent
import android.view.MotionEvent
import java.time.Duration
import java.util.concurrent.BlockingQueue
import java.util.concurrent.TimeUnit
import org.junit.Assert.fail

import org.hamcrest.Matcher
import org.hamcrest.MatcherAssert.assertThat
import org.junit.Assert.assertNull

private fun <T> getEvent(queue: BlockingQueue<T>, timeout: Duration): T? {
    return queue.poll(timeout.toMillis(), TimeUnit.MILLISECONDS)
}

class BlockingQueueEventVerifier(val queue: BlockingQueue<InputEvent>) {
    fun assertReceivedMotion(matcher: Matcher<MotionEvent>) {
        val event = getMotionEvent()
        assertThat("MotionEvent checks", event, matcher)
    }

    fun assertNoEvents() {
        val event = getEvent(queue, Duration.ofMillis(50))
        assertNull(event)
    }

    private fun getMotionEvent(): MotionEvent {
        val event = getEvent(queue, Duration.ofMillis(DEFAULT_DISPATCHING_TIMEOUT_MILLIS.toLong()))
        if (event == null) {
            fail("Did not get an event")
        }
        if (event is MotionEvent) {
            return event
        }
        fail("Instead of motion, got $event")
        throw RuntimeException("should not reach here")
    }
}