AI 145434: am: CL 145407 am: CL 145015 CTS: add test cases for LinkMovementMethod and HideReturnsTransformationMethod.
  Original author: sus
  Merged from: //branches/cupcake/...
  Original author: android-build

Automated import of CL 145434
diff --git a/tests/tests/text/src/android/text/method/cts/HideReturnsTransformationMethodTest.java b/tests/tests/text/src/android/text/method/cts/HideReturnsTransformationMethodTest.java
new file mode 100644
index 0000000..ffbff7f
--- /dev/null
+++ b/tests/tests/text/src/android/text/method/cts/HideReturnsTransformationMethodTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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 dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import android.text.method.HideReturnsTransformationMethod;
+
+import junit.framework.TestCase;
+
+/**
+ * Test {@link HideReturnsTransformationMethod}.
+ */
+@TestTargetClass(HideReturnsTransformationMethod.class)
+public class HideReturnsTransformationMethodTest extends TestCase {
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test constructor "
+                + "HideReturnsTransformationMethod#HideReturnsTransformationMethod().",
+        method = "HideReturnsTransformationMethod",
+        args = {}
+    )
+    public void testConstructor() {
+        new HideReturnsTransformationMethod();
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test {@link HideReturnsTransformationMethod#getOriginal()}.",
+        method = "getOriginal",
+        args = {}
+    )
+    public void testGetOriginal() {
+        MyHideReturnsTranformationMethod method = new MyHideReturnsTranformationMethod();
+        TextMethodUtils.assertEquals(new char[] { '\r' }, method.getOriginal());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test {@link HideReturnsTransformationMethod#getInstance()}.",
+        method = "getInstance",
+        args = {}
+    )
+    public void testGetInstance() {
+        HideReturnsTransformationMethod method0 = HideReturnsTransformationMethod.getInstance();
+        assertNotNull(method0);
+
+        HideReturnsTransformationMethod method1 = HideReturnsTransformationMethod.getInstance();
+        assertSame(method0, method1);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test {@link HideReturnsTransformationMethod#getReplacement()}.",
+        method = "getReplacement",
+        args = {}
+    )
+    public void testGetReplacement() {
+        MyHideReturnsTranformationMethod method = new MyHideReturnsTranformationMethod();
+        TextMethodUtils.assertEquals(new char[] { '\uFEFF' }, method.getReplacement());
+    }
+
+    private static class MyHideReturnsTranformationMethod extends HideReturnsTransformationMethod {
+        @Override
+        protected char[] getOriginal() {
+            return super.getOriginal();
+        }
+
+        @Override
+        protected char[] getReplacement() {
+            return super.getReplacement();
+        }
+    }
+}
diff --git a/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java b/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java
new file mode 100644
index 0000000..57c6d33
--- /dev/null
+++ b/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java
@@ -0,0 +1,679 @@
+/*
+ * 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 dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.ToBeFixed;
+
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.text.Selection;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.method.LinkMovementMethod;
+import android.text.method.MovementMethod;
+import android.text.style.ClickableSpan;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.TextView.BufferType;
+
+/**
+ * Test {@link LinkMovementMethod}. 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
+ */
+@TestTargetClass(LinkMovementMethod.class)
+public class LinkMovementMethodTest extends
+        ActivityInstrumentationTestCase2<StubActivity> {
+    private static final String CONTENT = "clickable\nunclickable\nclickable";
+
+    private LinkMovementMethod mMethod;
+
+    private TextView mView;
+
+    private Spannable mSpannable;
+
+    private MockClickableSpan mClickable0;
+
+    private MockClickableSpan mClickable1;
+
+    public LinkMovementMethodTest() {
+        super("com.android.cts.stub", StubActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mMethod = new LinkMovementMethod();
+
+        // Set the content view with a text view which contains 3 lines,
+        mView = new TextView(getActivity());
+        mView.setText(CONTENT, BufferType.SPANNABLE);
+        getInstrumentation().runOnMainSync(new Runnable() {
+            public void run() {
+                getActivity().setContentView(mView);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        mSpannable = (Spannable) mView.getText();
+        // make first line clickable
+        mClickable0 = markClickable(0, CONTENT.indexOf('\n'));
+        // make last line clickable
+        mClickable1 = markClickable(CONTENT.lastIndexOf('\n'), CONTENT.length());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test constructor LinkMovementMethod#LinkMovementMethod().",
+        method = "LinkMovementMethod",
+        args = {}
+    )
+    public void testConstructor() {
+        new LinkMovementMethod();
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test {@link LinkMovementMethod#getInstance()}. "
+                + "This is a method for creating singleton.",
+        method = "getInstance",
+        args = {}
+    )
+    public void testGetInstance() {
+        MovementMethod method0 = LinkMovementMethod.getInstance();
+        assertTrue(method0 instanceof LinkMovementMethod);
+
+        MovementMethod method1 = LinkMovementMethod.getInstance();
+        assertNotNull(method1);
+        assertSame(method0, method1);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test {@link LinkMovementMethod#onTakeFocus(TextView, Spannable, int)}. "
+                + "The parameter textView is useless.",
+        method = "onTakeFocus",
+        args = {TextView.class, Spannable.class, int.class}
+    )
+    @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+            + "should be added into javadoc of LinkMovementMethod#onTakeFocus(TextView, Spannable, "
+            + "int) when the params text is null")
+    public void testOnTakeFocus() {
+        LinkMovementMethod method = new LinkMovementMethod();
+        Spannable spannable = new SpannableString("test sequence");
+        Selection.setSelection(spannable, 0, spannable.length());
+
+        assertSelection(spannable, 0, spannable.length());
+        assertEquals(2, spannable.getSpans(0, spannable.length(), Object.class).length);
+        method.onTakeFocus(null, spannable, View.FOCUS_UP);
+        assertSelection(spannable, -1);
+        assertEquals(1, spannable.getSpans(0, spannable.length(), Object.class).length);
+        Object span = spannable.getSpans(0, spannable.length(), Object.class)[0];
+        assertEquals(0, spannable.getSpanStart(span));
+        assertEquals(0, spannable.getSpanEnd(span));
+        assertEquals(Spanned.SPAN_POINT_POINT, spannable.getSpanFlags(span));
+
+        // focus forwards
+        Selection.setSelection(spannable, 0, spannable.length());
+        assertSelection(spannable, 0, spannable.length());
+        assertEquals(3, spannable.getSpans(0, spannable.length(), Object.class).length);
+        method.onTakeFocus(null, spannable, View.FOCUS_RIGHT);
+        assertSelection(spannable, -1);
+        assertEquals(0, spannable.getSpans(0, spannable.length(), Object.class).length);
+
+        // force adding span while focus backward
+        method.onTakeFocus(null, spannable, View.FOCUS_UP);
+        // param direction is unknown(0)
+        Selection.setSelection(spannable, 0, spannable.length());
+        assertSelection(spannable, 0, spannable.length());
+        assertEquals(3, spannable.getSpans(0, spannable.length(), Object.class).length);
+        method.onTakeFocus(null, spannable, 0);
+        assertSelection(spannable, -1);
+        assertEquals(0, spannable.getSpans(0, spannable.length(), Object.class).length);
+
+        // null parameters
+        try {
+            method.onTakeFocus(new TextView(getActivity()), null, View.FOCUS_RIGHT);
+            fail("The method did not throw NullPointerException when param spannable is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test {@link LinkMovementMethod#onKeyDown(TextView, Spannable, int, KeyEvent)}.",
+        method = "onKeyDown",
+        args = {TextView.class, Spannable.class, int.class, KeyEvent.class}
+    )
+    @UiThreadTest
+    @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+            + "should be added into javadoc of LinkMovementMethod#onKeyDown(TextView, Spannable, "
+            + "int, KeyEvent) when the params widget, buffer or event is null")
+    public void testOnKeyDown() {
+        // no selection
+        assertSelection(mSpannable, -1);
+        mClickable0.reset();
+        mClickable1.reset();
+        assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_ENTER,
+                new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)));
+        assertFalse(mClickable0.hasCalledOnClick());
+        assertFalse(mClickable1.hasCalledOnClick());
+
+        // select clickable0
+        Selection.setSelection(mSpannable, mSpannable.getSpanStart(mClickable0),
+                mSpannable.getSpanEnd(mClickable0));
+        mClickable0.reset();
+        mClickable1.reset();
+        assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER,
+                new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER)));
+        assertTrue(mClickable0.hasCalledOnClick());
+        assertFalse(mClickable1.hasCalledOnClick());
+
+        // select unclickable
+        Selection.setSelection(mSpannable, mSpannable.getSpanEnd(mClickable0),
+                mSpannable.getSpanStart(mClickable1));
+        mClickable0.reset();
+        mClickable1.reset();
+        assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_ENTER,
+                new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)));
+        assertFalse(mClickable0.hasCalledOnClick());
+        assertFalse(mClickable1.hasCalledOnClick());
+
+        // select all clickables(more than one)
+        Selection.selectAll(mSpannable);
+        mClickable0.reset();
+        mClickable1.reset();
+        assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER,
+                new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER)));
+        assertFalse(mClickable0.hasCalledOnClick());
+        assertFalse(mClickable1.hasCalledOnClick());
+
+        // part of selection is clickable
+        Selection.setSelection(mSpannable, mSpannable.getSpanEnd(mClickable0),
+                mSpannable.getSpanEnd(mClickable1));
+        mClickable0.reset();
+        mClickable1.reset();
+        assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER,
+                new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER)));
+        assertFalse(mClickable0.hasCalledOnClick());
+        assertTrue(mClickable1.hasCalledOnClick());
+
+        // selection contains only clickable1 and repeat count of the event is not 0
+        Selection.setSelection(mSpannable, mSpannable.getSpanEnd(mClickable0),
+        mSpannable.getSpanEnd(mClickable1));
+        long now = SystemClock.uptimeMillis();
+        KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN,
+                KeyEvent.KEYCODE_DPAD_CENTER, 1);
+
+        mClickable0.reset();
+        mClickable1.reset();
+        assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER, event));
+        assertFalse(mClickable0.hasCalledOnClick());
+        assertFalse(mClickable1.hasCalledOnClick());
+
+        // null parameters
+        try {
+            mMethod.onKeyDown(null, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER,
+                    new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER));
+            fail("The method did not throw NullPointerException when param view is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            mMethod.onKeyDown(mView, null, KeyEvent.KEYCODE_DPAD_CENTER,
+                    new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER));
+            fail("The method did not throw NullPointerException when param spannable is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER, null);
+            fail("The method did not throw NullPointerException when param keyEvent is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test {@link LinkMovementMethod#onKeyUp(TextView, Spannable, int, KeyEvent)}. "
+                + "It always returns false, and all parameters are never read.",
+        method = "onKeyUp",
+        args = {TextView.class, Spannable.class, int.class, KeyEvent.class}
+    )
+    @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. There is no "
+            + "document about the behaviour of this method.")
+    public void testOnKeyUp() {
+        LinkMovementMethod method = new LinkMovementMethod();
+        // always returns false
+        assertFalse(method.onKeyUp(null, null, 0, null));
+        assertFalse(method.onKeyUp(new TextView(getActivity()), null, 0, null));
+        assertFalse(method.onKeyUp(null, new SpannableString("blahblah"), 0, null));
+        assertFalse(method.onKeyUp(null, null, KeyEvent.KEYCODE_0,
+                new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0)));
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test {@link LinkMovementMethod#onTouchEvent(TextView, Spannable, MotionEvent)} ",
+        method = "onTouchEvent",
+        args = {TextView.class, Spannable.class, MotionEvent.class}
+    )
+    @UiThreadTest
+    @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+            + "should be added into javadoc of LinkMovementMethod#onTouchEvent(TextView, "
+            + "Spannable, MotionEvent) when the params widget, buffer or event is null")
+    public void testOnTouchEvent() {
+        assertSelection(mSpannable, -1);
+
+        // press on first line (Clickable)
+        assertTrue(pressOnLine(0));
+        assertSelectClickableLeftToRight(mSpannable, mClickable0);
+
+        // release on first line
+        assertFalse(mClickable0.hasCalledOnClick());
+        assertTrue(releaseOnLine(0));
+        assertTrue(mClickable0.hasCalledOnClick());
+
+        // press on second line (unclickable)
+        assertSelectClickableLeftToRight(mSpannable, mClickable0);
+        // just clear selection
+        pressOnLine(1);
+        assertSelection(mSpannable, -1);
+
+        // press on last line  (Clickable)
+        assertTrue(pressOnLine(2));
+        assertSelectClickableLeftToRight(mSpannable, mClickable1);
+
+        // release on last line
+        assertFalse(mClickable1.hasCalledOnClick());
+        assertTrue(releaseOnLine(2));
+        assertTrue(mClickable1.hasCalledOnClick());
+
+        // release on second line (unclickable)
+        assertSelectClickableLeftToRight(mSpannable, mClickable1);
+        // just clear selection
+        releaseOnLine(1);
+        assertSelection(mSpannable, -1);
+
+        // null parameters
+        long now = SystemClock.uptimeMillis();
+        int y = (mView.getLayout().getLineTop(1) + mView.getLayout().getLineBottom(1)) / 2;
+        try {
+            mMethod.onTouchEvent(null, mSpannable,
+                    MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 5, y, 0));
+            fail("The method did not throw NullPointerException when param view is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            mMethod.onTouchEvent(mView, null,
+                    MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 5, y, 0));
+            fail("The method did not throw NullPointerException when param spannable is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            mMethod.onTouchEvent(mView, mSpannable, null);
+            fail("The method did not throw NullPointerException when param keyEvent is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test {@link LinkMovementMethod#up(TextView, Spannable)}. It is protected. "
+                + "Use extended class to test.",
+        method = "up",
+        args = {TextView.class, Spannable.class}
+    )
+    @UiThreadTest
+    @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+            + "should be added into javadoc of LinkMovementMethod#up(TextView, Spannable) "
+            + "when the params widget or buffer or is null")
+    public void testUp() {
+        final MyLinkMovementMethod method = new MyLinkMovementMethod();
+        assertSelection(mSpannable, -1);
+
+        assertTrue(method.up(mView, mSpannable));
+        assertSelectClickableRightToLeft(mSpannable, mClickable1);
+
+        assertTrue(method.up(mView, mSpannable));
+        assertSelectClickableRightToLeft(mSpannable, mClickable0);
+
+        assertFalse(method.up(mView, mSpannable));
+        assertSelectClickableRightToLeft(mSpannable, mClickable0);
+
+        // null parameters
+        try {
+            method.up(null, mSpannable);
+            fail("The method did not throw NullPointerException when param view is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            method.up(mView, null);
+            fail("The method did not throw NullPointerException when param spannable is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test {@link LinkMovementMethod#down(TextView, Spannable)}. It is protected. "
+                + "Use extended class to test.",
+        method = "down",
+        args = {TextView.class, Spannable.class}
+    )
+    @UiThreadTest
+    @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+            + "should be added into javadoc of LinkMovementMethod#down(TextView, Spannable) "
+            + "when the params widget or buffer or is null")
+    public void testDown() {
+        final MyLinkMovementMethod method = new MyLinkMovementMethod();
+        assertSelection(mSpannable, -1);
+
+        assertTrue(method.down(mView, mSpannable));
+        assertSelectClickableLeftToRight(mSpannable, mClickable0);
+
+        assertTrue(method.down(mView, mSpannable));
+        assertSelectClickableLeftToRight(mSpannable, mClickable1);
+
+        assertFalse(method.down(mView, mSpannable));
+        assertSelectClickableLeftToRight(mSpannable, mClickable1);
+
+        // null parameters
+        try {
+            method.down(null, mSpannable);
+            fail("The method did not throw NullPointerException when param view is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            method.down(mView, null);
+            fail("The method did not throw NullPointerException when param spannable is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test {@link LinkMovementMethod#left(TextView, Spannable)}. It is protected. "
+                + "Use extended class to test.",
+        method = "left",
+        args = {TextView.class, Spannable.class}
+    )
+    @UiThreadTest
+    @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+            + "should be added into javadoc of LinkMovementMethod#left(TextView, Spannable) "
+            + "when the params widget or buffer or is null")
+    public void testLeft() {
+        final MyLinkMovementMethod method = new MyLinkMovementMethod();
+        assertSelection(mSpannable, -1);
+
+        assertTrue(method.left(mView, mSpannable));
+        assertSelectClickableRightToLeft(mSpannable, mClickable1);
+
+        assertTrue(method.left(mView, mSpannable));
+        assertSelectClickableRightToLeft(mSpannable, mClickable0);
+
+        assertFalse(method.left(mView, mSpannable));
+        assertSelectClickableRightToLeft(mSpannable, mClickable0);
+
+        // null parameters
+        try {
+            method.left(null, mSpannable);
+            fail("The method did not throw NullPointerException when param view is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            method.left(mView, null);
+            fail("The method did not throw NullPointerException when param spannable is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test {@link LinkMovementMethod#right(TextView, Spannable)}. It is protected. "
+                + "Use extended class to test.",
+        method = "right",
+        args = {TextView.class, Spannable.class}
+    )
+    @UiThreadTest
+    @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+            + "should be added into javadoc of LinkMovementMethod#right(TextView, Spannable) "
+            + "when the params widget or buffer or is null")
+    public void testRight() {
+        final MyLinkMovementMethod method = new MyLinkMovementMethod();
+        assertSelection(mSpannable, -1);
+
+        assertTrue(method.right(mView, mSpannable));
+        assertSelectClickableLeftToRight(mSpannable, mClickable0);
+
+        assertTrue(method.right(mView, mSpannable));
+        assertSelectClickableLeftToRight(mSpannable, mClickable1);
+
+        assertFalse(method.right(mView, mSpannable));
+        assertSelectClickableLeftToRight(mSpannable, mClickable1);
+
+        // null parameters
+        try {
+            method.right(null, mSpannable);
+            fail("The method did not throw NullPointerException when param view is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            method.right(mView, null);
+            fail("The method did not throw NullPointerException when param spannable is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "Test {@link LinkMovementMethod#up(TextView, Spannable)}.",
+            method = "up",
+            args = {TextView.class, Spannable.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "Test {@link LinkMovementMethod#down(TextView, Spannable)}.",
+            method = "down",
+            args = {TextView.class, Spannable.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "Test {@link LinkMovementMethod#right(TextView, Spannable)}.",
+            method = "left",
+            args = {TextView.class, Spannable.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "Test {@link LinkMovementMethod#left(TextView, Spannable)}.",
+            method = "right",
+            args = {TextView.class, Spannable.class}
+        )
+    })
+    @UiThreadTest
+    @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. There is no "
+            + "document about the behaviour of these methods when the spannable text is not "
+            + "clickcable.")
+    public void testMoveAroundUnclickable() {
+        final MyLinkMovementMethod method = new MyLinkMovementMethod();
+        mSpannable.removeSpan(mClickable0);
+        mSpannable.removeSpan(mClickable1);
+        assertSelection(mSpannable, -1);
+
+        assertFalse(method.up(mView, mSpannable));
+        assertSelection(mSpannable, -1);
+
+        assertFalse(method.down(mView, mSpannable));
+        assertSelection(mSpannable, -1);
+
+        assertFalse(method.left(mView, mSpannable));
+        assertSelection(mSpannable, -1);
+
+        assertFalse(method.right(mView, mSpannable));
+        assertSelection(mSpannable, -1);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test {@link LinkMovementMethod#initialize(TextView, Spannable)}.",
+        method = "initialize",
+        args = {TextView.class, Spannable.class}
+    )
+    @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete. @throws clause "
+            + "should be added into javadoc of LinkMovementMethod#initialize(TextView, Spannable) "
+            + "when the params text is null")
+    public void testInitialize() {
+        LinkMovementMethod method = new LinkMovementMethod();
+        Spannable spannable = new SpannableString("test sequence");
+        method.onTakeFocus(null, spannable, View.FOCUS_UP);
+        Selection.setSelection(spannable, 0, spannable.length());
+
+        assertSelection(spannable, 0, spannable.length());
+        assertEquals(3, spannable.getSpans(0, spannable.length(), Object.class).length);
+        method.initialize(null, spannable);
+        assertSelection(spannable, -1);
+        assertEquals(0, spannable.getSpans(0, spannable.length(), Object.class).length);
+
+        try {
+            method.initialize(mView, null);
+            fail("The method did not throw NullPointerException when param spannable is null.");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    private MockClickableSpan markClickable(final int start, final int end) {
+        final MockClickableSpan clickableSpan = new MockClickableSpan();
+        getInstrumentation().runOnMainSync(new Runnable() {
+            public void run() {
+                mSpannable.setSpan(clickableSpan, start, end, Spanned.SPAN_MARK_MARK);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        return clickableSpan;
+    }
+
+    private boolean performMotionOnLine(int line, int action) {
+        int x = (mView.getLayout().getLineStart(line) + mView.getLayout().getLineEnd(line)) / 2;
+        int y = (mView.getLayout().getLineTop(line) + mView.getLayout().getLineBottom(line)) / 2;
+        long now = SystemClock.uptimeMillis();
+
+        return mMethod.onTouchEvent(mView, mSpannable,
+                MotionEvent.obtain(now, now, action, x, y, 0));
+    }
+
+    private boolean pressOnLine(int line) {
+        return performMotionOnLine(line, MotionEvent.ACTION_DOWN);
+    }
+
+    private boolean releaseOnLine(int line) {
+        return performMotionOnLine(line, MotionEvent.ACTION_UP);
+    }
+
+    private void assertSelection(Spannable spannable, int start, int end) {
+        assertEquals(start, Selection.getSelectionStart(spannable));
+        assertEquals(end, Selection.getSelectionEnd(spannable));
+    }
+
+    private void assertSelection(Spannable spannable, int position) {
+        assertSelection(spannable, position, position);
+    }
+
+    private void assertSelectClickableLeftToRight(Spannable spannable,
+            MockClickableSpan clickableSpan) {
+        assertSelection(spannable, spannable.getSpanStart(clickableSpan),
+                spannable.getSpanEnd(clickableSpan));
+    }
+
+    private void assertSelectClickableRightToLeft(Spannable spannable,
+            MockClickableSpan clickableSpan) {
+        assertSelection(spannable,  spannable.getSpanEnd(clickableSpan),
+                spannable.getSpanStart(clickableSpan));
+    }
+
+    private static class MyLinkMovementMethod extends LinkMovementMethod {
+        @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);
+        }
+    }
+
+    private static class MockClickableSpan extends ClickableSpan {
+        private boolean mHasCalledOnClick;
+
+        @Override
+        public void onClick(View widget) {
+            mHasCalledOnClick = true;
+        }
+
+        public boolean hasCalledOnClick() {
+            return mHasCalledOnClick;
+        }
+
+        public void reset() {
+            mHasCalledOnClick = false;
+        }
+    }
+}