/*
 * 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 android.cts.util.WidgetTestUtils;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.method.MovementMethod;
import android.text.method.ScrollingMovementMethod;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.TextView;
import android.widget.TextView.BufferType;

/**
 * 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
 */
public class ScrollingMovementMethodTest extends ActivityInstrumentationTestCase2<CtsActivity> {
    private static final int LITTLE_SPACE = 20;

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

    private TextView mTextView;

    private Spannable mSpannable;

    private int mScaledTouchSlop;

    public ScrollingMovementMethodTest() {
        super("com.android.cts.text", CtsActivity.class);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mTextView = new TextView(getActivity());
        mTextView.setText(THREE_LINES_TEXT, BufferType.EDITABLE);
        mSpannable = (Spannable) mTextView.getText();
        mScaledTouchSlop = ViewConfiguration.get(getActivity()).getScaledTouchSlop();
    }

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

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

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

    public void testOnTouchEventHorizontalMotion() throws Throwable {
        /*
         * All these assertions depends on whether the TextView has a layout.The text view will not
         * get layout in setContent method but in otherhandler's function. Assertion which is
         * following the setContent will not get the expecting result. It have to wait all the
         * handlers' operations on the UiTread to finish. So all these cases are divided into
         * several steps,setting the content at first, waiting the layout, and checking the
         * assertion at last.
         */
        final ScrollingMovementMethod method = new ScrollingMovementMethod();
        runActionOnUiThread(new Runnable() {
            public void run() {
                mTextView.setText("hello world", BufferType.SPANNABLE);
                mTextView.setSingleLine();
                mSpannable = (Spannable) mTextView.getText();
                int width = WidgetTestUtils.convertDipToPixels(getActivity(), LITTLE_SPACE);
                getActivity().setContentView(mTextView,
                        new ViewGroup.LayoutParams(width, ViewGroup.LayoutParams.WRAP_CONTENT));
            }
        });
        assertNotNull(mTextView.getLayout());

        float rightMost = mTextView.getLayout().getLineRight(0) - mTextView.getWidth()
                + mTextView.getTotalPaddingLeft() + mTextView.getTotalPaddingRight();
        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));
            }
        }));
    }

    public void testOnTouchEventVerticalMotion() throws Throwable {
        /*
         * All these assertions depends on whether the TextView has a layout.The text view will not
         * get layout in setContent method but in otherhandler's function. Assertion which is
         * following the setContent will not get the expecting result. It have to wait all the
         * handlers' operations on the UiTread to finish. So all these cases are divided into
         * several steps,setting the content at first, waiting the layout, and checking the
         * assertion at last.
         */
        final ScrollingMovementMethod method = new ScrollingMovementMethod();
        runActionOnUiThread(new Runnable() {
            public void run() {
                mTextView.setLines(1);
                getActivity().setContentView(mTextView,
                        new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
            }
        });
        assertNotNull(mTextView.getLayout());

        float bottom = mTextView.getLayout().getHeight() - mTextView.getHeight()
                + mTextView.getTotalPaddingTop() + mTextView.getTotalPaddingBottom();
        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));
            }
        }));
    }

    public void testOnTouchEventExceptional() throws Throwable {
        /*
         * All these assertions depends on whether the TextView has a layout.The text view will not
         * get layout in setContent method but in otherhandler's function. Assertion which is
         * following the setContent will not get the expecting result. It have to wait all the
         * handlers' operations on the UiTread to finish. So all these cases are divided into
         * several steps,setting the content at first, waiting the layout, and checking the
         * assertion at last.
         */
        runActionOnUiThread(new Runnable() {
            public void run() {
                int width = WidgetTestUtils.convertDipToPixels(getActivity(), LITTLE_SPACE);
                getActivity().setContentView(mTextView,
                        new ViewGroup.LayoutParams(width, ViewGroup.LayoutParams.WRAP_CONTENT));
            }
        });
        assertNotNull(mTextView.getLayout());

        runActionOnUiThread(new Runnable() {
            public void run() {
                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
                }
            }
        });
    }

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

    public void testOnKeyDownVerticalMovement() throws Throwable {
        /*
         * All these assertions depends on whether the TextView has a layout.The text view will not
         * get layout in setContent method but in otherhandler's function. Assertion which is
         * following the setContent will not get the expecting result. It have to wait all the
         * handlers' operations on the UiTread to finish. So all these cases are divided into
         * several steps,setting the content at first, waiting the layout, and checking the
         * assertion at last.
         */
        runActionOnUiThread(new Runnable() {
            public void run() {
                getActivity().setContentView(mTextView);
            }
        });
        assertNotNull(mTextView.getLayout());

        assertVisibleLineInTextView(0);
        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
        runActionOnUiThread(new Runnable() {
            public void run() {
                method.onKeyDown(mTextView, null, KeyEvent.KEYCODE_DPAD_DOWN,
                        new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN));
            }
        });
        assertVisibleLineInTextView(1);

        runActionOnUiThread(new Runnable() {
            public void run() {
                method.onKeyDown(mTextView, null, KeyEvent.KEYCODE_DPAD_UP,
                        new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP));
            }
        });
        assertVisibleLineInTextView(0);
    }

    public void testOnKeyDownHorizontalMovement() throws Throwable {
        /*
         * All these assertions depends on whether the TextView has a layout.The text view will not
         * get layout in setContent method but in otherhandler's function. Assertion which is
         * following the setContent will not get the expecting result. It have to wait all the
         * handlers' operations on the UiTread to finish. So all these cases are divided into
         * several steps,setting the content at first, waiting the layout, and checking the
         * assertion at last.
         */
        runActionOnUiThread(new Runnable() {
            public void run() {
                mTextView.setText("short");
                mTextView.setSingleLine();
                int width = WidgetTestUtils.convertDipToPixels(getActivity(), LITTLE_SPACE);
                getActivity().setContentView(mTextView,
                        new ViewGroup.LayoutParams(width, ViewGroup.LayoutParams.WRAP_CONTENT));
            }
        });
        assertNotNull(mTextView.getLayout());

        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
        int previousScrollX = mTextView.getScrollX();
        runActionOnUiThread(new Runnable() {
            public void run() {
                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(new Runnable() {
            public void run() {
                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();
        assertVisibleLineInTextView(0);
        runActionOnUiThread(new Runnable() {
            public void run() {
                assertFalse(method.onKeyDown(mTextView, mSpannable, 0,
                        new KeyEvent(KeyEvent.ACTION_DOWN, 0)));
            }
        });
        assertEquals(previousScrollX, mTextView.getScrollX());
        assertVisibleLineInTextView(0);
    }

    public void testOnKeyDownExceptions() throws Throwable {
        /*
         * All these assertions depends on whether the TextView has a layout.The text view will not
         * get layout in setContent method but in otherhandler's function. Assertion which is
         * following the setContent will not get the expecting result. It have to wait all the
         * handlers' operations on the UiTread to finish. So all these cases are divided into
         * several steps,setting the content at first, waiting the layout, and checking the
         * assertion at last.
         */
        runActionOnUiThread(new Runnable() {
            public void run() {
                getActivity().setContentView(mTextView);
            }
        });
        assertNotNull(mTextView.getLayout());

        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
        runActionOnUiThread(new Runnable() {
            public void run() {
                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
                }
            }
        });
    }

    public void testVerticalMovement() throws Throwable {
        /*
         * All these assertions depends on whether the TextView has a layout.The text view will not
         * get layout in setContent method but in otherhandler's function. Assertion which is
         * following the setContent will not get the expecting result. It have to wait all the
         * handlers' operations on the UiTread to finish. So all these cases are divided into
         * several steps,setting the content at first, waiting the layout, and checking the
         * assertion at last.
         */
        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
        runActionOnUiThread(new Runnable() {
            public void run() {
                mTextView.setLines(1);
                getActivity().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);
            }
        }));
        assertVisibleLineInTextView(1);

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

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

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

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

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

        runActionOnUiThread(new Runnable() {
            public void run() {
                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
                }
            }
        });
    }

    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
        }

        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
        }
    }

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

    public void testOnTrackballEvent() {
        long now = SystemClock.uptimeMillis();
        MotionEvent event = MotionEvent.obtain(now, now, 0, 2, -2, 0);
        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));
    }

    public void testOnKeyUp() {
        ScrollingMovementMethod method = new ScrollingMovementMethod();
        SpannableString spannable = new SpannableString("Test Content");
        KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
        TextView view = new TextView(getActivity());

        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));
    }

    public void testOnTakeFocus() throws Throwable {
        /*
         * All these assertions depends on whether the TextView has a layout.The text view will not
         * get layout in setContent method but in otherhandler's function. Assertion which is
         * following the setContent will not get the expecting result. It have to wait all the
         * handlers' operations on the UiTread to finish. So all these cases are divided into
         * several steps,setting the content at first, waiting the layout, and checking the
         * assertion at last.
         */
        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(new Runnable() {
            public void run() {
                int height = WidgetTestUtils.convertDipToPixels(getActivity(), LITTLE_SPACE);
                getActivity().setContentView(mTextView,
                        new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                                height));
            }
        });
        Layout layout = mTextView.getLayout();
        assertNotNull(layout);

        int previousScrollY = mTextView.getScrollY();
        runActionOnUiThread(new Runnable() {
            public void run() {
                method.onTakeFocus(mTextView, mSpannable, View.FOCUS_BACKWARD);
            }
        });
        assertTrue(mTextView.getScrollY() >= previousScrollY);
        assertVisibleLineInTextView(2);

        previousScrollY = mTextView.getScrollY();
        runActionOnUiThread(new Runnable() {
            public void run() {
                method.onTakeFocus(mTextView, mSpannable, View.FOCUS_FORWARD);
            }
        });
        assertTrue(mTextView.getScrollY() <= previousScrollY);
        assertVisibleLineInTextView(0);

        runActionOnUiThread(new Runnable() {
            public void run() {
                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
                }
            }
        });
    }

    public void testHorizontalMovement() throws Throwable {
        /*
         * All these assertions depends on whether the TextView has a layout.The text view will not
         * get layout in setContent method but in otherhandler's function. Assertion which is
         * following the setContent will not get the expecting result. It have to wait all the
         * handlers' operations on the UiTread to finish. So all these cases are divided into
         * several steps,setting the content at first, waiting the layout, and checking the
         * assertion at last.
         */
        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
        runActionOnUiThread(new Runnable() {
            public void run() {
                mTextView.setText("short");
                mTextView.setSingleLine();
                int width = WidgetTestUtils.convertDipToPixels(getActivity(), LITTLE_SPACE);
                getActivity().setContentView(mTextView,
                        new ViewGroup.LayoutParams(width, ViewGroup.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());
    }

    public void testOnKeyOther() throws Throwable {
        runActionOnUiThread(new Runnable() {
            public void run() {
                getActivity().setContentView(mTextView);
            }
        });
        assertNotNull(mTextView.getLayout());

        assertVisibleLineInTextView(0);
        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
        runActionOnUiThread(new Runnable() {
            public void run() {
                method.onKeyOther(mTextView, null,
                        new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE,
                                KeyEvent.KEYCODE_DPAD_DOWN, 2));
            }
        });
        assertVisibleLineInTextView(1);

        runActionOnUiThread(new Runnable() {
            public void run() {
                method.onKeyOther(mTextView, null,
                        new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE,
                                KeyEvent.KEYCODE_DPAD_UP, 2));
            }
        });
        assertVisibleLineInTextView(0);
    }

    private void assertVisibleLineInTextView(int line) {
        Layout layout = mTextView.getLayout();
        int scrollY = mTextView.getScrollY();
        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 {
        runTestOnUiThread(actionRunner);
        getInstrumentation().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);
        }
    }
}
