/*
 * Copyright (C) 2008 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 android.text.method.cts;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import android.app.Activity;
import android.app.Instrumentation;
import android.os.SystemClock;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.method.MovementMethod;
import android.text.method.ScrollingMovementMethod;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup.LayoutParams;
import android.widget.TextView;
import android.widget.TextView.BufferType;

import androidx.test.InstrumentationRegistry;
import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.MediumTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;

import com.android.compatibility.common.util.WidgetTestUtils;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
 * Test {@link ScrollingMovementMethod}. The class is an implementation of interface
 * {@link MovementMethod}. The typical usage of {@link MovementMethod} is tested in
 * {@link android.widget.cts.TextViewTest} and this test case is only focused on the
 * implementation of the methods.
 *
 * @see android.widget.cts.TextViewTest
 */
@MediumTest
@RunWith(AndroidJUnit4.class)
public class ScrollingMovementMethodTest {
    private static final int LITTLE_SPACE = 20;

    private static final String THREE_LINES_TEXT = "first line\nsecond line\nlast line";

    private Instrumentation mInstrumentation;
    private Activity mActivity;
    private TextView mTextView;
    private Spannable mSpannable;
    private int mScaledTouchSlop;

    @Rule
    public ActivityTestRule<CtsActivity> mActivityRule = new ActivityTestRule<>(CtsActivity.class);

    @UiThreadTest
    @Before
    public void setup() throws Throwable {
        mInstrumentation = InstrumentationRegistry.getInstrumentation();
        mActivity = mActivityRule.getActivity();
        mTextView = new TextViewNoIme(mActivity);
        mTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
        mTextView.setText(THREE_LINES_TEXT, BufferType.EDITABLE);
        mSpannable = (Spannable) mTextView.getText();
        mScaledTouchSlop = ViewConfiguration.get(mActivity).getScaledTouchSlop();
    }

    @Test
    public void testConstructor() {
        new ScrollingMovementMethod();
    }

    @Test
    public void testGetInstance() {
        final MovementMethod method0 = ScrollingMovementMethod.getInstance();
        assertTrue(method0 instanceof ScrollingMovementMethod);

        final MovementMethod method1 = ScrollingMovementMethod.getInstance();
        assertSame(method0, method1);
    }

    @Test
    public void testOnTouchEventHorizontalMotion() throws Throwable {
        final ScrollingMovementMethod method = new ScrollingMovementMethod();
        runActionOnUiThread(() -> {
            mTextView.setText("hello world", BufferType.SPANNABLE);
            mTextView.setSingleLine();
            mSpannable = (Spannable) mTextView.getText();
            final int width = WidgetTestUtils.convertDipToPixels(mActivity, LITTLE_SPACE);
            mActivity.setContentView(mTextView,
                    new LayoutParams(width, LayoutParams.WRAP_CONTENT));
        });
        assertNotNull(mTextView.getLayout());

        final float rightMost = mTextView.getLayout().getLineRight(0) - mTextView.getWidth()
                + mTextView.getTotalPaddingLeft() + mTextView.getTotalPaddingRight();
        final int leftMost = mTextView.getScrollX();

        final long now = SystemClock.uptimeMillis();
        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // press
                mResult = method.onTouchEvent(mTextView, mSpannable,
                        MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 0, 0, 0));
            }
        }));

        final int tinyDist = -(mScaledTouchSlop - 1);
        int previousScrollX = mTextView.getScrollX();
        assertFalse(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // move for short distance
                mResult = method.onTouchEvent(mTextView, mSpannable,
                        MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, tinyDist, 0, 0));
            }
        }));
        assertEquals(previousScrollX, mTextView.getScrollX());

        assertFalse(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // release
                mResult = method.onTouchEvent(mTextView, mSpannable,
                        MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, tinyDist, 0, 0));
            }
        }));

        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // press
                mResult = method.onTouchEvent(mTextView, mSpannable,
                        MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 0, 0, 0));
            }
        }));

        final int distFar = -mScaledTouchSlop;
        previousScrollX = mTextView.getScrollX();
        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // move for enough distance
                mResult = method.onTouchEvent(mTextView, mSpannable,
                        MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, distFar, 0, 0));
            }
        }));
        assertTrue(mTextView.getScrollX() > previousScrollX);
        assertTrue(mTextView.getScrollX() < rightMost);

        previousScrollX = mTextView.getScrollX();
        final int distTooFar = (int) (-rightMost * 10);
        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // move for long distance
                mResult = method.onTouchEvent(mTextView, mSpannable,
                        MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, distTooFar, 0, 0));
            }
        }));
        assertTrue(mTextView.getScrollX() > previousScrollX);
        assertEquals(rightMost, mTextView.getScrollX(), 1.0f);

        previousScrollX = mTextView.getScrollX();
        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // move back
                mResult = method.onTouchEvent(mTextView, mSpannable,
                        MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, 0, 0, 0));
            }
        }));
        assertTrue(mTextView.getScrollX() < previousScrollX);
        assertEquals(leftMost, mTextView.getScrollX());

        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // release
                mResult = method.onTouchEvent(mTextView, mSpannable,
                        MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 0, 0, 0));
            }
        }));
    }

    @Test
    public void testOnTouchEventVerticalMotion() throws Throwable {
        final ScrollingMovementMethod method = new ScrollingMovementMethod();
        runActionOnUiThread(() -> {
            mTextView.setLines(1);
            mActivity.setContentView(mTextView,
                    new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
        });
        assertNotNull(mTextView.getLayout());

        final float bottom = mTextView.getLayout().getHeight() - mTextView.getHeight()
                + mTextView.getTotalPaddingTop() + mTextView.getTotalPaddingBottom();
        final int top = mTextView.getScrollY();

        final long now = SystemClock.uptimeMillis();
        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // press
                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
                        MotionEvent.ACTION_DOWN, 0, 0, 0));
            }
        }));

        final int tinyDist = -(mScaledTouchSlop - 1);
        int previousScrollY = mTextView.getScrollY();
        assertFalse(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // move for short distance
                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
                        MotionEvent.ACTION_MOVE, 0, tinyDist, 0));
            }
        }));
        assertEquals(previousScrollY, mTextView.getScrollY());

        assertFalse(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // release
                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
                        MotionEvent.ACTION_UP, 0, tinyDist, 0));
            }
        }));

        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // press
                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
                        MotionEvent.ACTION_DOWN, 0, 0, 0));
            }
        }));

        final int distFar = -mScaledTouchSlop;
        previousScrollY = mTextView.getScrollY();
        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // move for enough distance
                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
                        MotionEvent.ACTION_MOVE, 0, distFar, 0));
            }
        }));
        assertTrue(mTextView.getScrollY() > previousScrollY);
        assertTrue(mTextView.getScrollX() < bottom);

        previousScrollY = mTextView.getScrollY();
        final int distTooFar = (int) (-bottom * 10);
        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // move for long distance
                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
                        MotionEvent.ACTION_MOVE, 0, distTooFar, 0));
            }
        }));
        assertTrue(mTextView.getScrollY() > previousScrollY);
        assertEquals(bottom, mTextView.getScrollY(), 0f);

        previousScrollY = mTextView.getScrollY();
        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // move back
                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
                        MotionEvent.ACTION_MOVE, 0, 0, 0));
            }
        }));
        assertTrue(mTextView.getScrollY() < previousScrollY);
        assertEquals(top, mTextView.getScrollX());

        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                // release
                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
                        MotionEvent.ACTION_UP, 0, 0, 0));
            }
        }));
    }

    @Test
    public void testOnTouchEventExceptional() throws Throwable {
        runActionOnUiThread(() -> {
            final int width = WidgetTestUtils.convertDipToPixels(mActivity, LITTLE_SPACE);
            mActivity.setContentView(mTextView,
                    new LayoutParams(width, LayoutParams.WRAP_CONTENT));
        });
        assertNotNull(mTextView.getLayout());

        runActionOnUiThread(() -> {
            try {
                new ScrollingMovementMethod().onTouchEvent(mTextView, mSpannable, null);
            } catch (NullPointerException e) {
                // NPE is acceptable
            }

            long now = SystemClock.uptimeMillis();
            try {
                new ScrollingMovementMethod().onTouchEvent(mTextView, null,
                        MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 0, 0, 0));
            } catch (NullPointerException e) {
                // NPE is acceptable
            }

            try {
                new ScrollingMovementMethod().onTouchEvent(null, mSpannable,
                        MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 0, 0, 0));
            } catch (NullPointerException e) {
                // NPE is acceptable
            }

            new ScrollingMovementMethod().onTouchEvent(mTextView, mSpannable,
                    MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 0, 0, 0));
            try {
                new ScrollingMovementMethod().onTouchEvent(null, mSpannable,
                        MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, -10000, 0, 0));
            } catch (NullPointerException e) {
                // NPE is acceptable
            }

            try {
                new ScrollingMovementMethod().onTouchEvent(mTextView, null,
                        MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, -10000, 0, 0));
            } catch (NullPointerException e) {
                // NPE is acceptable
            }

            try {
                new ScrollingMovementMethod().onTouchEvent(null, mSpannable,
                        MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, -10000, 0, 0));
            } catch (NullPointerException e) {
                // NPE is acceptable
            }

            try {
                new ScrollingMovementMethod().onTouchEvent(mTextView, null,
                        MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, -10000, 0, 0));
            } catch (NullPointerException e) {
                // NPE is acceptable
            }
        });
    }

    @Test
    public void testCanSelectArbitrarily() {
        assertFalse(new ScrollingMovementMethod().canSelectArbitrarily());
    }

    @Test
    public void testOnKeyDownVerticalMovement() throws Throwable {
        runActionOnUiThread(() -> mActivity.setContentView(mTextView));
        assertNotNull(mTextView.getLayout());

        verifyVisibleLineInTextView(0);
        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
        runActionOnUiThread(() -> method.onKeyDown(mTextView, null, KeyEvent.KEYCODE_DPAD_DOWN,
                new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN)));
        verifyVisibleLineInTextView(1);

        runActionOnUiThread(() -> method.onKeyDown(mTextView, null, KeyEvent.KEYCODE_DPAD_UP,
                new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP)));
        verifyVisibleLineInTextView(0);
    }

    @Test
    public void testOnKeyDownHorizontalMovement() throws Throwable {
        runActionOnUiThread(() -> {
            mTextView.setText("short");
            mTextView.setSingleLine();
            final int width = WidgetTestUtils.convertDipToPixels(mActivity, LITTLE_SPACE);
            mActivity.setContentView(mTextView,
                    new LayoutParams(width, LayoutParams.WRAP_CONTENT));
        });
        assertNotNull(mTextView.getLayout());

        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
        int previousScrollX = mTextView.getScrollX();
        runActionOnUiThread(() -> method.onKeyDown(mTextView, (Spannable) mTextView.getText(),
                KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(KeyEvent.ACTION_DOWN,
                        KeyEvent.KEYCODE_DPAD_RIGHT)));
        assertTrue(mTextView.getScrollX() > previousScrollX);

        previousScrollX = mTextView.getScrollX();
        runActionOnUiThread(() -> method.onKeyDown(mTextView, (Spannable) mTextView.getText(),
                KeyEvent.KEYCODE_DPAD_LEFT, new KeyEvent(KeyEvent.ACTION_DOWN,
                        KeyEvent.KEYCODE_DPAD_LEFT)));
        assertTrue(mTextView.getScrollX() < previousScrollX);

        previousScrollX = mTextView.getScrollX();
        verifyVisibleLineInTextView(0);
        runActionOnUiThread(() -> assertFalse(method.onKeyDown(mTextView, mSpannable, 0,
                new KeyEvent(KeyEvent.ACTION_DOWN, 0))));
        assertEquals(previousScrollX, mTextView.getScrollX());
        verifyVisibleLineInTextView(0);
    }

    @Test
    public void testOnKeyDownExceptions() throws Throwable {
        runActionOnUiThread(() -> mActivity.setContentView(mTextView));
        assertNotNull(mTextView.getLayout());

        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
        runActionOnUiThread(() -> {
            try {
                method.onKeyDown(null, mSpannable, KeyEvent.KEYCODE_DPAD_RIGHT,
                        new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP));
            } catch (NullPointerException e) {
                // NPE is acceptable
            }

            try {
                method.onKeyDown(mTextView, null, KeyEvent.KEYCODE_DPAD_RIGHT,
                        new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP));
            } catch (NullPointerException e) {
                // NPE is acceptable
            }

            try {
                method.onKeyDown(mTextView, mSpannable, KeyEvent.KEYCODE_DPAD_RIGHT, null);
            } catch (NullPointerException e) {
                // NPE is acceptable
            }
        });
    }

    @Test
    public void testVerticalMovement() throws Throwable {
        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
        runActionOnUiThread(() -> {
            mTextView.setLines(1);
            mActivity.setContentView(mTextView,
                    new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
        });
        assertNotNull(mTextView.getLayout());

        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                mResult = method.down(mTextView, mSpannable);
            }
        }));
        verifyVisibleLineInTextView(1);

        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                mResult = method.down(mTextView, mSpannable);
            }
        }));
        verifyVisibleLineInTextView(2);

        assertFalse(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                mResult = method.down(mTextView, mSpannable);
            }
        }));
        verifyVisibleLineInTextView(2);

        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                mResult = method.up(mTextView, mSpannable);
            }
        }));
        verifyVisibleLineInTextView(1);

        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                mResult = method.up(mTextView, mSpannable);
            }
        }));
        verifyVisibleLineInTextView(0);

        assertFalse(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                mResult = method.up(mTextView, mSpannable);
            }
        }));
        verifyVisibleLineInTextView(0);

        runActionOnUiThread(() -> {
            try {
                method.up(null, mSpannable);
            } catch (NullPointerException e) {
                // NPE is acceptable
            }

            try {
                method.up(mTextView, null);
            } catch (NullPointerException e) {
                // NPE is acceptable
            }

            try {
                method.down(null, mSpannable);
            } catch (NullPointerException e) {
                // NPE is acceptable
            }

            try {
                method.down(mTextView, null);
            } catch (NullPointerException e) {
                // NPE is acceptable
            }
        });
    }

    @Test
    public void testMovementWithNullLayout() {
        assertNull(mTextView.getLayout());
        try {
            new MyScrollingMovementMethod().down(mTextView, mSpannable);
        } catch (NullPointerException e) {
            // NPE is acceptable
        }

        try {
            new MyScrollingMovementMethod().up(mTextView, mSpannable);
        } catch (NullPointerException e) {
            // NPE is acceptable
        }

        try {
            new MyScrollingMovementMethod().left(mTextView, mSpannable);
        } catch (NullPointerException e) {
            // NPE is acceptable
        }

        try {
            new MyScrollingMovementMethod().right(mTextView, mSpannable);
        } catch (NullPointerException e) {
            // NPE is acceptable
        }

        final long now = SystemClock.uptimeMillis();
        try {
            KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT);
            new ScrollingMovementMethod().onKeyDown(mTextView, mSpannable,
                    KeyEvent.KEYCODE_DPAD_RIGHT, event);
        } catch (NullPointerException e) {
            // NPE is acceptable
        }

        new ScrollingMovementMethod().onTouchEvent(mTextView, mSpannable,
                MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 0, 0, 0));
        try {
            new ScrollingMovementMethod().onTouchEvent(mTextView, mSpannable,
                    MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, - 10000, 0, 0));
        } catch (NullPointerException e) {
            // NPE is acceptable
        }
    }

    @Test
    public void testInitialize() {
        new ScrollingMovementMethod().initialize(null, null);
    }

    @Test
    public void testOnTrackballEvent() {
        final long now = SystemClock.uptimeMillis();
        final MotionEvent event = MotionEvent.obtain(now, now, 0, 2, -2, 0);
        final MyScrollingMovementMethod mockMethod = new MyScrollingMovementMethod();

        assertFalse(mockMethod.onTrackballEvent(mTextView, mSpannable, event));
        assertFalse(mockMethod.onTrackballEvent(null, mSpannable, event));
        assertFalse(mockMethod.onTrackballEvent(mTextView, mSpannable, null));
        assertFalse(mockMethod.onTrackballEvent(mTextView, null, event));
    }

    @UiThreadTest
    @Test
    public void testOnKeyUp() {
        final ScrollingMovementMethod method = new ScrollingMovementMethod();
        final SpannableString spannable = new SpannableString("Test Content");
        final KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
        final TextView view = new TextViewNoIme(mActivity);
        view.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);

        assertFalse(method.onKeyUp(view, spannable, KeyEvent.KEYCODE_0, event));
        assertFalse(method.onKeyUp(null, null, 0, null));
        assertFalse(method.onKeyUp(null, spannable, KeyEvent.KEYCODE_0, event));
        assertFalse(method.onKeyUp(view, null, KeyEvent.KEYCODE_0, event));
        assertFalse(method.onKeyUp(view, spannable, 0, event));
        assertFalse(method.onKeyUp(view, spannable, KeyEvent.KEYCODE_0, null));
    }

    @Test
    public void testOnTakeFocus() throws Throwable {
        final ScrollingMovementMethod method = new ScrollingMovementMethod();
        // wait until the text view gets layout
        assertNull(mTextView.getLayout());
        try {
            method.onTakeFocus(mTextView, mSpannable, View.FOCUS_BACKWARD);
        } catch (NullPointerException e) {
            // NPE is acceptable
        }

        runActionOnUiThread(() -> {
            final int height = WidgetTestUtils.convertDipToPixels(mActivity, LITTLE_SPACE);
            mActivity.setContentView(mTextView,
                    new LayoutParams(LayoutParams.MATCH_PARENT,
                            height));
        });
        final Layout layout = mTextView.getLayout();
        assertNotNull(layout);

        int previousScrollY = mTextView.getScrollY();
        runActionOnUiThread(() -> method.onTakeFocus(mTextView, mSpannable, View.FOCUS_BACKWARD));
        assertTrue(mTextView.getScrollY() >= previousScrollY);
        verifyVisibleLineInTextView(2);

        previousScrollY = mTextView.getScrollY();
        runActionOnUiThread(() -> method.onTakeFocus(mTextView, mSpannable, View.FOCUS_FORWARD));
        assertTrue(mTextView.getScrollY() <= previousScrollY);
        verifyVisibleLineInTextView(0);

        runActionOnUiThread(() -> {
            try {
                method.onTakeFocus(null, mSpannable, View.FOCUS_FORWARD);
            } catch (NullPointerException e) {
                // NPE is acceptable
            }

            try {
                method.onTakeFocus(mTextView, null, View.FOCUS_FORWARD);
            } catch (NullPointerException e) {
                // NPE is acceptable
            }
        });
    }

    @Test
    public void testHorizontalMovement() throws Throwable {
        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
        runActionOnUiThread(() -> {
            mTextView.setText("short");
            mTextView.setSingleLine();
            final DisplayMetrics dm = mActivity.getResources().getDisplayMetrics();
            final int width = (int) (LITTLE_SPACE * dm.scaledDensity);
            mActivity.setContentView(mTextView,
                    new LayoutParams(width, LayoutParams.WRAP_CONTENT));
        });
        assertNotNull(mTextView.getLayout());

        int previousScrollX = mTextView.getScrollX();
        assertTrue(getActionResult(new ActionRunnerWithResult() {

            public void run() {
                mResult = method.right(mTextView, mSpannable);
            }
        }));
        assertTrue(mTextView.getScrollX() > previousScrollX);

        previousScrollX = mTextView.getScrollX();
        assertFalse(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                mResult = method.right(mTextView, mSpannable);
            }
        }));
        assertEquals(previousScrollX, mTextView.getScrollX());

        previousScrollX = mTextView.getScrollX();
        assertTrue(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                mResult = method.left(mTextView, mSpannable);
            }
        }));
        assertTrue(mTextView.getScrollX() < previousScrollX);

        previousScrollX = mTextView.getScrollX();
        assertFalse(getActionResult(new ActionRunnerWithResult() {
            public void run() {
                mResult = method.left(mTextView, mSpannable);
            }
        }));
        assertEquals(previousScrollX, mTextView.getScrollX());
    }

    @Test
    public void testOnKeyOther() throws Throwable {
        runActionOnUiThread(() -> mActivity.setContentView(mTextView));
        assertNotNull(mTextView.getLayout());

        verifyVisibleLineInTextView(0);
        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
        runActionOnUiThread(() -> method.onKeyOther(mTextView, null,
                new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE,
                        KeyEvent.KEYCODE_DPAD_DOWN, 2)));
        verifyVisibleLineInTextView(1);

        runActionOnUiThread(() -> method.onKeyOther(mTextView, null,
                new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE,
                        KeyEvent.KEYCODE_DPAD_UP, 2)));
        verifyVisibleLineInTextView(0);
    }

    private void verifyVisibleLineInTextView(int line) {
        final Layout layout = mTextView.getLayout();
        final int scrollY = mTextView.getScrollY();
        final int padding = mTextView.getTotalPaddingTop() + mTextView.getTotalPaddingBottom();
        assertTrue(layout.getLineForVertical(scrollY) <= line);
        assertTrue(layout.getLineForVertical(scrollY + mTextView.getHeight() - padding) >= line);
    }

    private boolean getActionResult(ActionRunnerWithResult actionRunner) throws Throwable {
        runActionOnUiThread(actionRunner);
        return actionRunner.getResult();
    }

    private void runActionOnUiThread(Runnable actionRunner) throws Throwable {
        mActivityRule.runOnUiThread(actionRunner);
        mInstrumentation.waitForIdleSync();
    }

    private static abstract class ActionRunnerWithResult implements Runnable {
        protected boolean mResult = false;

        public boolean getResult() {
            return mResult;
        }
    }

    private static class MyScrollingMovementMethod extends ScrollingMovementMethod {
        @Override
        protected boolean down(TextView widget, Spannable buffer) {
            return super.down(widget, buffer);
        }

        @Override
        protected boolean left(TextView widget, Spannable buffer) {
            return super.left(widget, buffer);
        }

        @Override
        protected boolean right(TextView widget, Spannable buffer) {
            return super.right(widget, buffer);
        }

        @Override
        protected boolean up(TextView widget, Spannable buffer) {
            return super.up(widget, buffer);
        }
    }
}
