AI 145252: CTS: add test cases for android.widget.MultiAutoCompleteTextView

Automated import of CL 145252
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 5f54f5a..fcee464 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -270,6 +270,14 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.widget.cts.MultiAutoCompleteTextViewStubActivity"
+            android:label="MultiAutoCompleteTextView Test Activity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <activity android:name="android.hardware.cts.CameraStubActivity"
             android:label="CameraStubActivity"
             android:screenOrientation="landscape">
diff --git a/tests/res/layout/multi_auto_complete_text_view_layout.xml b/tests/res/layout/multi_auto_complete_text_view_layout.xml
new file mode 100644
index 0000000..38ef783
--- /dev/null
+++ b/tests/res/layout/multi_auto_complete_text_view_layout.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/text_country" />
+
+    <MultiAutoCompleteTextView android:id="@+id/country_edit"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"/>
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/text_name" />
+
+    <MultiAutoCompleteTextView android:id="@+id/name_edit"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"/>
+
+</LinearLayout>
+
diff --git a/tests/src/android/widget/cts/MultiAutoCompleteTextViewStubActivity.java b/tests/src/android/widget/cts/MultiAutoCompleteTextViewStubActivity.java
new file mode 100644
index 0000000..fa973a6
--- /dev/null
+++ b/tests/src/android/widget/cts/MultiAutoCompleteTextViewStubActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 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.widget.cts;
+
+import com.android.cts.stub.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A minimal application for MultiAutoCompleteTextView test.
+ */
+public class MultiAutoCompleteTextViewStubActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.multi_auto_complete_text_view_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java
new file mode 100644
index 0000000..0080e84
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java
@@ -0,0 +1,360 @@
+/*
+ * 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.widget.cts;
+
+import com.android.cts.stub.R;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.ToBeFixed;
+
+import org.xmlpull.v1.XmlPullParser;
+
+import android.app.Activity;
+import android.content.Context;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Xml;
+import android.view.KeyEvent;
+import android.widget.ArrayAdapter;
+import android.widget.Filter;
+import android.widget.MultiAutoCompleteTextView;
+import android.widget.MultiAutoCompleteTextView.CommaTokenizer;
+import android.widget.MultiAutoCompleteTextView.Tokenizer;
+
+@TestTargetClass(MultiAutoCompleteTextView.class)
+public class MultiAutoCompleteTextViewTest extends ActivityInstrumentationTestCase2
+        <MultiAutoCompleteTextViewStubActivity> {
+    private MultiAutoCompleteTextView mMultiAutoCompleteTextView_country;
+    private MultiAutoCompleteTextView mMultiAutoCompleteTextView_name;
+    private Activity mActivity;
+
+    public MultiAutoCompleteTextViewTest() {
+        super("com.android.cts.stub", MultiAutoCompleteTextViewStubActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+
+        mMultiAutoCompleteTextView_country = (MultiAutoCompleteTextView)mActivity
+                .findViewById(R.id.country_edit);
+        mMultiAutoCompleteTextView_name = (MultiAutoCompleteTextView)mActivity
+                .findViewById(R.id.name_edit);
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "MultiAutoCompleteTextView",
+            args = {android.content.Context.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "MultiAutoCompleteTextView",
+            args = {android.content.Context.class, android.util.AttributeSet.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "MultiAutoCompleteTextView",
+            args = {android.content.Context.class, android.util.AttributeSet.class, int.class}
+        )
+    })
+    @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete")
+    public void testConstructor() {
+        XmlPullParser parser = mActivity.getResources()
+                .getXml(R.layout.multi_auto_complete_text_view_layout);
+        AttributeSet attr = Xml.asAttributeSet(parser);
+
+        new MultiAutoCompleteTextView(mActivity);
+        new MultiAutoCompleteTextView(mActivity, attr);
+        new MultiAutoCompleteTextView(mActivity, attr, 0);
+
+        try {
+            new MultiAutoCompleteTextView(null);
+            fail("There should be a NullPointerException thrown out.");
+        } catch (NullPointerException e) {
+            // expected, test success
+        }
+
+        try {
+            new MultiAutoCompleteTextView(null, null);
+            fail("There should be a NullPointerException thrown out.");
+        } catch (NullPointerException e) {
+            // expected, test success
+        }
+
+        try {
+            new MultiAutoCompleteTextView(null, null, -1);
+            fail("There should be a NullPointerException thrown out.");
+        } catch (NullPointerException e) {
+            // expected, test success
+        }
+    }
+
+    @UiThreadTest
+    private void setText(MultiAutoCompleteTextView m, CharSequence c) {
+        m.setText(c);
+        m.setSelection(0, c.length());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setTokenizer",
+            args = {Tokenizer.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "enoughToFilter",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.NOT_FEASIBLE,
+            method = "performValidation",
+            args = {}
+        )
+    })
+    @UiThreadTest
+    @ToBeFixed(bug = "", explanation = "There will be an endless loop when call performValidation" +
+            " if using CommaTokenizer as the Tokenizer.")
+    public void testMultiAutoCompleteTextView() {
+        mMultiAutoCompleteTextView_country.setTokenizer(new CommaTokenizer());
+        mMultiAutoCompleteTextView_name.setTokenizer(new CommaTokenizer());
+
+        mMultiAutoCompleteTextView_country.setThreshold(3);
+        mMultiAutoCompleteTextView_name.setThreshold(2);
+
+        assertFalse(mMultiAutoCompleteTextView_country.enoughToFilter());
+        assertFalse(mMultiAutoCompleteTextView_name.enoughToFilter());
+
+        setText(mMultiAutoCompleteTextView_country, "Ar");
+        assertFalse(mMultiAutoCompleteTextView_country.enoughToFilter());
+
+        setText(mMultiAutoCompleteTextView_country, "Arg");
+        assertTrue(mMultiAutoCompleteTextView_country.enoughToFilter());
+
+        setText(mMultiAutoCompleteTextView_country, "Argentina");
+        assertTrue(mMultiAutoCompleteTextView_country.enoughToFilter());
+
+        setText(mMultiAutoCompleteTextView_name, "J");
+        assertFalse(mMultiAutoCompleteTextView_name.enoughToFilter());
+
+        setText(mMultiAutoCompleteTextView_name, "Ja");
+        assertTrue(mMultiAutoCompleteTextView_name.enoughToFilter());
+
+        setText(mMultiAutoCompleteTextView_name, "Jacky");
+        assertTrue(mMultiAutoCompleteTextView_name.enoughToFilter());
+
+        MockValidator v = new MockValidator();
+        v.setValid(true);
+        mMultiAutoCompleteTextView_name.setValidator(v);
+
+        // There will be an endless loop when using CommaTokenizer as the Tokenizer
+        // mMultiAutoCompleteTextView_name.performValidation();
+        mMultiAutoCompleteTextView_name.setValidator(null);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "performValidation",
+        args = {}
+    )
+    @UiThreadTest
+    public void testPerformValidation() {
+        MockValidator v = new MockValidator();
+        v.setValid(true);
+        mMultiAutoCompleteTextView_country.setValidator(v);
+        MockTokenizer t = new MockTokenizer();
+        mMultiAutoCompleteTextView_country.setTokenizer(t);
+        String str = new String("Foo, Android Test, OH");
+        mMultiAutoCompleteTextView_country.setText(str);
+        mMultiAutoCompleteTextView_country.performValidation();
+        assertEquals(str, mMultiAutoCompleteTextView_country.getText().toString());
+
+        v.setValid(false);
+        mMultiAutoCompleteTextView_country.performValidation();
+        assertEquals(str + ", ", mMultiAutoCompleteTextView_country.getText().toString());
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "performFiltering",
+            args = {java.lang.CharSequence.class, int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "performFiltering",
+            args = {java.lang.CharSequence.class, int.class, int.class, int.class}
+        )
+    })
+    @ToBeFixed(bug = "1400249", explanation = "it's hard to do unit test, should be tested by" +
+               " functional test.")
+    public void testPerformFiltering() {
+        MyMultiAutoCompleteTextView multiAutoCompleteTextView =
+            new MyMultiAutoCompleteTextView(mActivity);
+        CommaTokenizer t = new CommaTokenizer();
+        multiAutoCompleteTextView.setTokenizer(t);
+
+        ArrayAdapter<String> adapter = new ArrayAdapter<String>(mActivity,
+                R.layout.simple_dropdown_item_1line);
+        assertNotNull(adapter);
+
+        multiAutoCompleteTextView.setAdapter(adapter);
+        assertNotNull(multiAutoCompleteTextView.getFilter());
+
+        String text = "Android test.";
+        multiAutoCompleteTextView.setText(text);
+        multiAutoCompleteTextView.setSelection(0, 12);
+
+        multiAutoCompleteTextView.performFiltering(text, KeyEvent.KEYCODE_0);
+        assertNotNull(multiAutoCompleteTextView.getFilter());
+
+        multiAutoCompleteTextView.performFiltering(text, 0, text.length(), KeyEvent.KEYCODE_E);
+        assertNotNull(multiAutoCompleteTextView.getFilter());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "replaceText",
+        args = {java.lang.CharSequence.class}
+    )
+    public void testReplaceText() {
+        MyMultiAutoCompleteTextView multiAutoCompleteTextView =
+            new MyMultiAutoCompleteTextView(mActivity);
+        CommaTokenizer t = new CommaTokenizer();
+        multiAutoCompleteTextView.setTokenizer(t);
+
+        String text = "CTS.";
+        multiAutoCompleteTextView.setText(text);
+        assertEquals(text, multiAutoCompleteTextView.getText().toString());
+        multiAutoCompleteTextView.setSelection(0, text.length());
+
+        // set the selection range.
+        multiAutoCompleteTextView.replaceText("Android Test.");
+        assertEquals("Android Test., ", multiAutoCompleteTextView.getText().toString());
+
+        // do not set the selection range.
+        multiAutoCompleteTextView.replaceText("replace test");
+        assertEquals("Android Test., replace test, ",
+                multiAutoCompleteTextView.getText().toString());
+    }
+
+    private class MockTokenizer implements Tokenizer {
+        public int findTokenStart(CharSequence text, int cursor) {
+            int i = cursor;
+            while (i > 0 && (text.charAt(i - 1) == ' ' || text.charAt(i - 1) == ',')) {
+                i--;
+            }
+
+            while (i > 0 && text.charAt(i - 1) != ',') {
+                i--;
+            }
+
+            while (i < cursor && text.charAt(i) == ' ') {
+                i++;
+            }
+
+            return i;
+        }
+
+        public int findTokenEnd(CharSequence text, int cursor) {
+            int i = cursor;
+            int len = text.length();
+
+            while (i < len) {
+                if (text.charAt(i) == ',') {
+                    return i;
+                } else {
+                    i++;
+                }
+            }
+
+            return len;
+        }
+
+        public CharSequence terminateToken(CharSequence text) {
+            int i = text.length();
+
+            while (i > 0 && text.charAt(i - 1) == ' ') {
+                i--;
+            }
+
+            if (i > 0 && text.charAt(i - 1) == ',') {
+                return text;
+            } else {
+                if (text instanceof Spanned) {
+                    SpannableString sp = new SpannableString(text + ", ");
+                    TextUtils.copySpansFrom((Spanned)text, 0, text.length(), Object.class, sp, 0);
+                    return sp;
+                } else {
+                    return text + ", ";
+                }
+            }
+        }
+    }
+
+    private class MockValidator implements MultiAutoCompleteTextView.Validator {
+        private boolean mIsValid;
+
+        public void setValid(boolean b) {
+            mIsValid = b;
+        }
+
+        public boolean isValid(CharSequence text) {
+            return mIsValid;
+        }
+
+        public CharSequence fixText(CharSequence invalidText) {
+            return invalidText;
+        }
+    }
+
+    /**
+     * MyMultiAutoCompleteTextView
+     */
+    private class MyMultiAutoCompleteTextView extends MultiAutoCompleteTextView {
+        public MyMultiAutoCompleteTextView(Context c) {
+            super(c);
+        }
+
+        protected void performFiltering(CharSequence text, int keyCode) {
+            super.performFiltering(text, keyCode);
+        }
+
+        protected void performFiltering(CharSequence text, int start, int end, int keyCode) {
+            super.performFiltering(text, start, end, keyCode);
+        }
+
+        protected void replaceText(CharSequence text) {
+            super.replaceText(text);
+        }
+
+        protected Filter getFilter() {
+            return super.getFilter();
+        }
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextView_CommaTokenizerTest.java b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextView_CommaTokenizerTest.java
new file mode 100644
index 0000000..267dfa6
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextView_CommaTokenizerTest.java
@@ -0,0 +1,174 @@
+/*
+ * 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.widget.cts;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.ToBeFixed;
+
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.style.UnderlineSpan;
+import android.widget.MultiAutoCompleteTextView.CommaTokenizer;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(CommaTokenizer.class)
+public class MultiAutoCompleteTextView_CommaTokenizerTest extends TestCase {
+    private static final String TEST_TEXT = "first token, second token";
+    CommaTokenizer mCommaTokenizer;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mCommaTokenizer = new CommaTokenizer();
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "MultiAutoCompleteTextView.CommaTokenizer",
+        args = {}
+    )
+    public void testConstructor() {
+        new CommaTokenizer();
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "findTokenStart",
+        args = {java.lang.CharSequence.class, int.class}
+    )
+    @ToBeFixed(bug = "1695243", explanation = "does not declare the corner cases." +
+            " 1. cursor is out of bound. 2. text is null.")
+    public void testFindTokenStart() {
+        int indexOfSecondToken = TEST_TEXT.indexOf("second");
+        assertEquals(indexOfSecondToken,
+                mCommaTokenizer.findTokenStart(TEST_TEXT, indexOfSecondToken));
+        // cursor point to the space before "second".
+        // FIXME: does it worked as intended? findTokenStart does not exclude this leading
+        // space in this case.
+        assertEquals(indexOfSecondToken - 1,
+                mCommaTokenizer.findTokenStart(TEST_TEXT, indexOfSecondToken - 1));
+        assertEquals(indexOfSecondToken,
+                mCommaTokenizer.findTokenStart(TEST_TEXT, TEST_TEXT.length()));
+
+        // cursor point to the comma before "second"
+        assertEquals(0, mCommaTokenizer.findTokenStart(TEST_TEXT, indexOfSecondToken - 2));
+        assertEquals(0, mCommaTokenizer.findTokenStart(TEST_TEXT, 1));
+
+        assertEquals(-1, mCommaTokenizer.findTokenStart(TEST_TEXT, -1));
+        assertEquals(-2, mCommaTokenizer.findTokenStart(TEST_TEXT, -2));
+
+        try {
+            mCommaTokenizer.findTokenStart(TEST_TEXT, TEST_TEXT.length() + 1);
+            fail("did not throw IndexOutOfBoundsException when cursor is large than length");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            mCommaTokenizer.findTokenStart(null, TEST_TEXT.length());
+            fail("did not throw NullPointerException when text is null");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "findTokenEnd",
+        args = {java.lang.CharSequence.class, int.class}
+    )
+    @ToBeFixed(bug = "1695243", explanation = "does not declare the corner cases." +
+            " 1. cursor is out of bound. 2. text is null.")
+    public void testFindTokenEnd() {
+        int indexOfComma = TEST_TEXT.indexOf(",");
+
+        assertEquals(indexOfComma, mCommaTokenizer.findTokenEnd(TEST_TEXT, 0));
+        assertEquals(indexOfComma, mCommaTokenizer.findTokenEnd(TEST_TEXT, indexOfComma - 1));
+        assertEquals(indexOfComma, mCommaTokenizer.findTokenEnd(TEST_TEXT, indexOfComma));
+
+        assertEquals(TEST_TEXT.length(),
+                mCommaTokenizer.findTokenEnd(TEST_TEXT, indexOfComma + 1));
+        assertEquals(TEST_TEXT.length(),
+                mCommaTokenizer.findTokenEnd(TEST_TEXT, TEST_TEXT.length()));
+        assertEquals(TEST_TEXT.length(),
+                mCommaTokenizer.findTokenEnd(TEST_TEXT, TEST_TEXT.length() + 1));
+
+        try {
+            mCommaTokenizer.findTokenEnd(TEST_TEXT, -1);
+            fail("did not throw IndexOutOfBoundsException when cursor is -1");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            mCommaTokenizer.findTokenEnd(null, 1);
+            fail("did not throw NullPointerException when text is null");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "terminateToken",
+        args = {java.lang.CharSequence.class}
+    )
+    @ToBeFixed(bug = "1695243", explanation = "does not declare the corner cases." +
+            " 1. text is null." +
+            " 2. javadoc says ends with a token terminator (for example a space or comma)," +
+            " but actually ends with both comma and space")
+    public void testTerminateToken() {
+        String text = "end with comma,";
+        assertEquals(text, mCommaTokenizer.terminateToken(text));
+
+        text = "end without comma";
+        // ends with both comma and space
+        assertEquals(text + ", ", mCommaTokenizer.terminateToken(text));
+
+        text = "end without comma!";
+        // ends with both comma and space
+        assertEquals(text + ", ", mCommaTokenizer.terminateToken(text));
+
+        text = "has ending spaces   ";
+        assertEquals(text + ", ", mCommaTokenizer.terminateToken(text));
+
+        text = "has ending spaces ,   ";
+        assertEquals(text, mCommaTokenizer.terminateToken(text));
+
+        text = "test Spanned text";
+        SpannableString spannableString = new SpannableString(text);
+        SpannableString expected = new SpannableString(text + ", ");
+        UnderlineSpan what = new UnderlineSpan();
+        spannableString.setSpan(what, 0, spannableString.length(),
+                Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+
+        SpannableString actual = (SpannableString) mCommaTokenizer.terminateToken(spannableString);
+        assertEquals(expected.toString(), actual.toString());
+        assertEquals(0, actual.getSpanStart(what));
+        assertEquals(spannableString.length(), actual.getSpanEnd(what));
+
+        try {
+            mCommaTokenizer.terminateToken(null);
+            fail("did not throw NullPointerException when text is null");
+        } catch (NullPointerException e) {
+            // expected, test success
+        }
+    }
+}