/*
 * 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.widget.R;

import org.xmlpull.v1.XmlPullParser;

import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.cts.util.PollingCheck;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
import android.test.suitebuilder.annotation.MediumTest;
import android.util.AttributeSet;
import android.util.Pair;
import android.util.SparseBooleanArray;
import android.util.Xml;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnDrawListener;
import android.view.animation.LayoutAnimationController;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import junit.framework.Assert;

public class ListViewTest extends ActivityInstrumentationTestCase2<ListViewCtsActivity> {
    private final String[] mCountryList = new String[] {
        "Argentina", "Australia", "China", "France", "Germany", "Italy", "Japan", "United States"
    };
    private final String[] mNameList = new String[] {
        "Jacky", "David", "Kevin", "Michael", "Andy"
    };
    private final String[] mEmptyList = new String[0];

    private ListView mListView;
    private Activity mActivity;
    private Instrumentation mInstrumentation;
    private AttributeSet mAttributeSet;
    private ArrayAdapter<String> mAdapter_countries;
    private ArrayAdapter<String> mAdapter_names;
    private ArrayAdapter<String> mAdapter_empty;

    public ListViewTest() {
        super("com.android.cts.widget", ListViewCtsActivity.class);
    }

    protected void setUp() throws Exception {
        super.setUp();

        mActivity = getActivity();
        mInstrumentation = getInstrumentation();
        XmlPullParser parser = mActivity.getResources().getXml(R.layout.listview_layout);
        mAttributeSet = Xml.asAttributeSet(parser);

        mAdapter_countries = new ArrayAdapter<String>(mActivity,
                android.R.layout.simple_list_item_1, mCountryList);
        mAdapter_names = new ArrayAdapter<String>(mActivity, android.R.layout.simple_list_item_1,
                mNameList);
        mAdapter_empty = new ArrayAdapter<String>(mActivity, android.R.layout.simple_list_item_1,
                mEmptyList);

        mListView = (ListView) mActivity.findViewById(R.id.listview_default);
    }

    public void testConstructor() {
        new ListView(mActivity);
        new ListView(mActivity, mAttributeSet);
        new ListView(mActivity, mAttributeSet, 0);

        try {
            new ListView(null);
            fail("There should be a NullPointerException thrown out. ");
        } catch (NullPointerException e) {
            // expected, test success.
        }

        try {
            new ListView(null, null);
            fail("There should be a NullPointerException thrown out. ");
        } catch (NullPointerException e) {
            // expected, test success.
        }

        try {
            new ListView(null, null, -1);
            fail("There should be a NullPointerException thrown out. ");
        } catch (NullPointerException e) {
            // expected, test success.
        }
    }

    public void testGetMaxScrollAmount() {
        setAdapter(mAdapter_empty);
        int scrollAmount = mListView.getMaxScrollAmount();
        assertEquals(0, scrollAmount);

        setAdapter(mAdapter_names);
        scrollAmount = mListView.getMaxScrollAmount();
        assertTrue(scrollAmount > 0);
    }

    private void setAdapter(final ArrayAdapter<String> adapter) {
        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setAdapter(adapter);
            }
        });
        mInstrumentation.waitForIdleSync();
    }

    public void testAccessDividerHeight() {
        final HasDrawnListener drawListener = new HasDrawnListener();

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.getViewTreeObserver().addOnDrawListener(drawListener);
                mListView.setAdapter(mAdapter_countries);
            }
        });
        mInstrumentation.waitForIdleSync();

        Drawable d = mListView.getDivider();
        final Rect r = d.getBounds();
        new PollingCheck() {
            @Override
            protected boolean check() {
                return r.bottom - r.top > 0;
            }
        }.run();

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                drawListener.reset();
                mListView.setDividerHeight(20);
            }
        });
        mInstrumentation.waitForIdleSync();
        assertTrue(drawListener.hasDrawn());
        assertEquals(20, mListView.getDividerHeight());
        assertEquals(20, r.bottom - r.top);

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                drawListener.reset();
                mListView.setDividerHeight(10);
            }
        });
        mInstrumentation.waitForIdleSync();
        assertTrue(drawListener.hasDrawn());
        assertEquals(10, mListView.getDividerHeight());
        assertEquals(10, r.bottom - r.top);
    }

    static class HasDrawnListener implements OnDrawListener {
        private boolean mHasDrawn;

        @Override
        public void onDraw() {
            mHasDrawn = true;
        }

        public boolean hasDrawn() {
            return mHasDrawn;
        }

        public void reset() {
            mHasDrawn = false;
        }
    }

    public void testAccessItemsCanFocus() {
        mListView.setItemsCanFocus(true);
        assertTrue(mListView.getItemsCanFocus());

        mListView.setItemsCanFocus(false);
        assertFalse(mListView.getItemsCanFocus());

        // TODO: how to check?
    }

    public void testAccessAdapter() {
        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setAdapter(mAdapter_countries);
            }
        });
        mInstrumentation.waitForIdleSync();

        assertSame(mAdapter_countries, mListView.getAdapter());
        assertEquals(mCountryList.length, mListView.getCount());

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setAdapter(mAdapter_names);
            }
        });
        mInstrumentation.waitForIdleSync();

        assertSame(mAdapter_names, mListView.getAdapter());
        assertEquals(mNameList.length, mListView.getCount());
    }

    @UiThreadTest
    public void testAccessItemChecked() {
        // NONE mode
        mListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
        assertEquals(ListView.CHOICE_MODE_NONE, mListView.getChoiceMode());

        mListView.setItemChecked(1, true);
        assertEquals(ListView.INVALID_POSITION, mListView.getCheckedItemPosition());
        assertFalse(mListView.isItemChecked(1));

        // SINGLE mode
        mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        assertEquals(ListView.CHOICE_MODE_SINGLE, mListView.getChoiceMode());

        mListView.setItemChecked(2, true);
        assertEquals(2, mListView.getCheckedItemPosition());
        assertTrue(mListView.isItemChecked(2));

        mListView.setItemChecked(3, true);
        assertEquals(3, mListView.getCheckedItemPosition());
        assertTrue(mListView.isItemChecked(3));
        assertFalse(mListView.isItemChecked(2));

        // test attempt to uncheck a item that wasn't checked to begin with
        mListView.setItemChecked(4, false);
        // item three should still be checked
        assertEquals(3, mListView.getCheckedItemPosition());
        assertFalse(mListView.isItemChecked(4));
        assertTrue(mListView.isItemChecked(3));
        assertFalse(mListView.isItemChecked(2));

        mListView.setItemChecked(4, true);
        assertTrue(mListView.isItemChecked(4));
        mListView.clearChoices();
        assertEquals(ListView.INVALID_POSITION, mListView.getCheckedItemPosition());
        assertFalse(mListView.isItemChecked(4));

        // MULTIPLE mode
        mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        assertEquals(ListView.CHOICE_MODE_MULTIPLE, mListView.getChoiceMode());

        mListView.setItemChecked(1, true);
        assertEquals(ListView.INVALID_POSITION, mListView.getCheckedItemPosition());
        SparseBooleanArray array = mListView.getCheckedItemPositions();
        assertTrue(array.get(1));
        assertFalse(array.get(2));
        assertTrue(mListView.isItemChecked(1));
        assertFalse(mListView.isItemChecked(2));

        mListView.setItemChecked(2, true);
        mListView.setItemChecked(3, false);
        mListView.setItemChecked(4, true);

        assertTrue(array.get(1));
        assertTrue(array.get(2));
        assertFalse(array.get(3));
        assertTrue(array.get(4));
        assertTrue(mListView.isItemChecked(1));
        assertTrue(mListView.isItemChecked(2));
        assertFalse(mListView.isItemChecked(3));
        assertTrue(mListView.isItemChecked(4));

        mListView.clearChoices();
        assertFalse(array.get(1));
        assertFalse(array.get(2));
        assertFalse(array.get(3));
        assertFalse(array.get(4));
        assertFalse(mListView.isItemChecked(1));
        assertFalse(mListView.isItemChecked(2));
        assertFalse(mListView.isItemChecked(3));
        assertFalse(mListView.isItemChecked(4));
    }

    public void testAccessFooterView() {
        final TextView footerView1 = new TextView(mActivity);
        footerView1.setText("footerview1");
        final TextView footerView2 = new TextView(mActivity);
        footerView2.setText("footerview2");

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setFooterDividersEnabled(true);
            }
        });
        mInstrumentation.waitForIdleSync();
        assertEquals(0, mListView.getFooterViewsCount());

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.addFooterView(footerView1, null, true);
            }
        });
        mInstrumentation.waitForIdleSync();
        assertEquals(1, mListView.getFooterViewsCount());

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.addFooterView(footerView2);
            }
        });

        mInstrumentation.waitForIdleSync();
        assertEquals(2, mListView.getFooterViewsCount());

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setAdapter(mAdapter_countries);
            }
        });
        mInstrumentation.waitForIdleSync();

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.removeFooterView(footerView1);
            }
        });
        mInstrumentation.waitForIdleSync();
        assertEquals(1, mListView.getFooterViewsCount());

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.removeFooterView(footerView2);
            }
        });
        mInstrumentation.waitForIdleSync();
        assertEquals(0, mListView.getFooterViewsCount());
    }

    public void testAccessHeaderView() {
        final TextView headerView1 = (TextView) mActivity.findViewById(R.id.headerview1);
        final TextView headerView2 = (TextView) mActivity.findViewById(R.id.headerview2);

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setHeaderDividersEnabled(true);
            }
        });
        mInstrumentation.waitForIdleSync();
        assertEquals(0, mListView.getHeaderViewsCount());

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.addHeaderView(headerView2, null, true);
            }
        });
        mInstrumentation.waitForIdleSync();
        assertEquals(1, mListView.getHeaderViewsCount());

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.addHeaderView(headerView1);
            }
        });
        mInstrumentation.waitForIdleSync();
        assertEquals(2, mListView.getHeaderViewsCount());
    }

    public void testHeaderFooterType() throws Throwable {
        final TextView headerView = new TextView(getActivity());
        final List<Pair<View, View>> mismatch = new ArrayList<Pair<View, View>>();
        final ArrayAdapter adapter = new ArrayAdapter<String>(mActivity,
                android.R.layout.simple_list_item_1, mNameList) {
            @Override
            public int getItemViewType(int position) {
                return position == 0 ? AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER :
                        super.getItemViewType(position - 1);
            }

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                if (position == 0) {
                    if (convertView != null && convertView != headerView) {
                        mismatch.add(new Pair<View, View>(headerView, convertView));
                    }
                    return headerView;
                } else {
                    return super.getView(position - 1, convertView, parent);
                }
            }

            @Override
            public int getCount() {
                return super.getCount() + 1;
            }
        };
        runTestOnUiThread(new Runnable() {
            @Override
            public void run() {
                mListView.setAdapter(adapter);
            }
        });
        getInstrumentation().waitForIdleSync();

        runTestOnUiThread(new Runnable() {
            @Override
            public void run() {
                adapter.notifyDataSetChanged();
            }
        });
        getInstrumentation().waitForIdleSync();

        assertEquals(0, mismatch.size());
    }

    public void testAccessDivider() {
        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setAdapter(mAdapter_countries);
            }
        });
        mInstrumentation.waitForIdleSync();

        Drawable defaultDrawable = mListView.getDivider();
        final Rect r = defaultDrawable.getBounds();
        new PollingCheck() {
            @Override
            protected boolean check() {
                return r.bottom - r.top > 0;
            }
        }.run();

        final Drawable d = mActivity.getResources().getDrawable(R.drawable.scenery);

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setDivider(d);
            }
        });
        mInstrumentation.waitForIdleSync();
        assertSame(d, mListView.getDivider());
        assertEquals(d.getBounds().height(), mListView.getDividerHeight());

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setDividerHeight(10);
            }
        });
        mInstrumentation.waitForIdleSync();
        assertEquals(10, mListView.getDividerHeight());
        assertEquals(10, d.getBounds().height());
    }

    public void testSetSelection() {
        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setAdapter(mAdapter_countries);
            }
        });
        mInstrumentation.waitForIdleSync();

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setSelection(1);
            }
        });
        mInstrumentation.waitForIdleSync();
        String item = (String) mListView.getSelectedItem();
        assertEquals(mCountryList[1], item);

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setSelectionFromTop(5, 0);
            }
        });
        mInstrumentation.waitForIdleSync();
        item = (String) mListView.getSelectedItem();
        assertEquals(mCountryList[5], item);

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setSelectionAfterHeaderView();
            }
        });
        mInstrumentation.waitForIdleSync();
        item = (String) mListView.getSelectedItem();
        assertEquals(mCountryList[0], item);
    }

    public void testOnKeyUpDown() {
        // implementation details, do NOT test
    }

    public void testPerformItemClick() {
        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setAdapter(mAdapter_countries);
            }
        });
        mInstrumentation.waitForIdleSync();

        mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setSelection(2);
            }
        });
        mInstrumentation.waitForIdleSync();

        final TextView child = (TextView) mAdapter_countries.getView(2, null, mListView);
        assertNotNull(child);
        assertEquals(mCountryList[2], child.getText().toString());
        final long itemID = mAdapter_countries.getItemId(2);
        assertEquals(2, itemID);

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.performItemClick(child, 2, itemID);
            }
        });
        mInstrumentation.waitForIdleSync();

        MockOnItemClickListener onClickListener = new MockOnItemClickListener();
        mListView.setOnItemClickListener(onClickListener);

        assertNull(onClickListener.getView());
        assertEquals(0, onClickListener.getPosition());
        assertEquals(0, onClickListener.getID());

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.performItemClick(child, 2, itemID);
            }
        });
        mInstrumentation.waitForIdleSync();

        assertSame(child, onClickListener.getView());
        assertEquals(2, onClickListener.getPosition());
        assertEquals(2, onClickListener.getID());
    }

    public void testSaveAndRestoreInstanceState() {
        // implementation details, do NOT test
    }

    public void testDispatchKeyEvent() {
        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setAdapter(mAdapter_countries);
                mListView.requestFocus();
            }
        });
        mInstrumentation.waitForIdleSync();
        assertTrue(mListView.hasFocus());

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setSelection(1);
            }
        });
        mInstrumentation.waitForIdleSync();
        String item = (String) mListView.getSelectedItem();
        assertEquals(mCountryList[1], item);

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A);
                mListView.dispatchKeyEvent(keyEvent);
            }
        });
        mInstrumentation.waitForIdleSync();

        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN);
                mListView.dispatchKeyEvent(keyEvent);
                mListView.dispatchKeyEvent(keyEvent);
                mListView.dispatchKeyEvent(keyEvent);
            }
        });
        mInstrumentation.waitForIdleSync();
        item = (String)mListView.getSelectedItem();
        assertEquals(mCountryList[4], item);
    }

    public void testRequestChildRectangleOnScreen() {
        mInstrumentation.runOnMainSync(new Runnable() {
            public void run() {
                mListView.setAdapter(mAdapter_countries);
            }
        });
        mInstrumentation.waitForIdleSync();

        TextView child = (TextView) mAdapter_countries.getView(0, null, mListView);
        assertNotNull(child);
        assertEquals(mCountryList[0], child.getText().toString());

        Rect rect = new Rect(0, 0, 10, 10);
        assertFalse(mListView.requestChildRectangleOnScreen(child, rect, false));

        // TODO: how to check?
    }

    public void testOnTouchEvent() {
        // implementation details, do NOT test
    }

    @UiThreadTest
    public void testCanAnimate() {
        MyListView listView = new MyListView(mActivity, mAttributeSet);

        assertFalse(listView.canAnimate());
        listView.setAdapter(mAdapter_countries);
        assertFalse(listView.canAnimate());

        LayoutAnimationController controller = new LayoutAnimationController(
                mActivity, mAttributeSet);
        listView.setLayoutAnimation(controller);

        assertTrue(listView.canAnimate());
    }

    @UiThreadTest
    public void testDispatchDraw() {
        // implementation details, do NOT test
    }

    @UiThreadTest
    public void testFindViewTraversal() {
        MyListView listView = new MyListView(mActivity, mAttributeSet);
        TextView headerView = (TextView) mActivity.findViewById(R.id.headerview1);

        assertNull(listView.findViewTraversal(R.id.headerview1));

        listView.addHeaderView(headerView);
        assertNotNull(listView.findViewTraversal(R.id.headerview1));
        assertSame(headerView, listView.findViewTraversal(R.id.headerview1));
    }

    @UiThreadTest
    public void testFindViewWithTagTraversal() {
        MyListView listView = new MyListView(mActivity, mAttributeSet);
        TextView headerView = (TextView) mActivity.findViewById(R.id.headerview1);

        assertNull(listView.findViewWithTagTraversal("header"));

        headerView.setTag("header");
        listView.addHeaderView(headerView);
        assertNotNull(listView.findViewWithTagTraversal("header"));
        assertSame(headerView, listView.findViewWithTagTraversal("header"));
    }

    public void testLayoutChildren() {
        // TODO: how to test?
    }

    public void testOnFinishInflate() {
        // implementation details, do NOT test
    }

    public void testOnFocusChanged() {
        // implementation details, do NOT test
    }

    public void testOnMeasure() {
        // implementation details, do NOT test
    }

    /**
     * MyListView for test
     */
    private static class MyListView extends ListView {
        public MyListView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        @Override
        protected boolean canAnimate() {
            return super.canAnimate();
        }

        @Override
        protected void dispatchDraw(Canvas canvas) {
            super.dispatchDraw(canvas);
        }

        @Override
        protected View findViewTraversal(int id) {
            return super.findViewTraversal(id);
        }

        @Override
        protected View findViewWithTagTraversal(Object tag) {
            return super.findViewWithTagTraversal(tag);
        }

        @Override
        protected void layoutChildren() {
            super.layoutChildren();
        }
    }

    private static class MockOnItemClickListener implements OnItemClickListener {
        private View mView;
        private int mPosition;
        private long mID;

        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            mView = view;
            mPosition = position;
            mID = id;
        }

        public View getView() {
            return mView;
        }

        public int getPosition() {
            return mPosition;
        }

        public long getID() {
            return mID;
        }
    }

    /**
     * The following functions are merged from frameworktest.
     */
    @MediumTest
    public void testRequestLayout() throws Exception {
        ListView listView = new ListView(mActivity);
        List<String> items = new ArrayList<>();
        items.add("hello");
        Adapter<String> adapter = new Adapter<String>(mActivity, 0, items);
        listView.setAdapter(adapter);

        int measureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY);

        adapter.notifyDataSetChanged();
        listView.measure(measureSpec, measureSpec);
        listView.layout(0, 0, 100, 100);

        MockView childView = (MockView) listView.getChildAt(0);

        childView.requestLayout();
        childView.onMeasureCalled = false;
        listView.measure(measureSpec, measureSpec);
        listView.layout(0, 0, 100, 100);
        Assert.assertTrue(childView.onMeasureCalled);
    }

    @MediumTest
    public void testNoSelectableItems() throws Exception {
        ListView listView = new ListView(mActivity);
        // We use a header as the unselectable item to remain after the selectable one is removed.
        listView.addHeaderView(new View(mActivity), null, false);
        List<String> items = new ArrayList<>();
        items.add("hello");
        Adapter<String> adapter = new Adapter<String>(mActivity, 0, items);
        listView.setAdapter(adapter);

        listView.setSelection(1);

        int measureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY);

        adapter.notifyDataSetChanged();
        listView.measure(measureSpec, measureSpec);
        listView.layout(0, 0, 100, 100);

        items.remove(0);

        adapter.notifyDataSetChanged();
        listView.measure(measureSpec, measureSpec);
        listView.layout(0, 0, 100, 100);
    }

    private class MockView extends View {

        public boolean onMeasureCalled = false;

        public MockView(Context context) {
            super(context);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            onMeasureCalled = true;
        }
    }

    private class Adapter<T> extends ArrayAdapter<T> {

        public Adapter(Context context, int resource, List<T> objects) {
            super(context, resource, objects);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            return new MockView(getContext());
        }
    }

    public void testTransientStateUnstableIds() throws Exception {
        final ListView listView = mListView;
        final ArrayList<String> items = new ArrayList<String>(Arrays.asList(mCountryList));
        final ArrayAdapter<String> adapter = new ArrayAdapter<String>(mActivity,
                android.R.layout.simple_list_item_1, items);

        mInstrumentation.runOnMainSync(new Runnable() {
            @Override
            public void run() {
                listView.setAdapter(adapter);
            }
        });
        mInstrumentation.waitForIdleSync();

        final View oldItem = listView.getChildAt(2);
        final CharSequence oldText = ((TextView) oldItem.findViewById(android.R.id.text1))
                .getText();
        oldItem.setHasTransientState(true);

        mInstrumentation.runOnMainSync(new Runnable() {
            @Override
            public void run() {
                adapter.remove(adapter.getItem(0));
                adapter.notifyDataSetChanged();
            }
        });
        mInstrumentation.waitForIdleSync();

        final View newItem = listView.getChildAt(2);
        final CharSequence newText = ((TextView) newItem.findViewById(android.R.id.text1))
                .getText();

        Assert.assertFalse(oldText.equals(newText));
    }

    public void testTransientStateStableIds() throws Exception {
        final ListView listView = mListView;
        final ArrayList<String> items = new ArrayList<String>(Arrays.asList(mCountryList));
        final StableArrayAdapter<String> adapter = new StableArrayAdapter<String>(mActivity,
                android.R.layout.simple_list_item_1, items);

        mInstrumentation.runOnMainSync(new Runnable() {
            @Override
            public void run() {
                listView.setAdapter(adapter);
            }
        });
        mInstrumentation.waitForIdleSync();

        final Object tag = new Object();
        final View oldItem = listView.getChildAt(2);
        final CharSequence oldText = ((TextView) oldItem.findViewById(android.R.id.text1))
                .getText();
        oldItem.setHasTransientState(true);
        oldItem.setTag(tag);

        mInstrumentation.runOnMainSync(new Runnable() {
            @Override
            public void run() {
                adapter.remove(adapter.getItem(0));
                adapter.notifyDataSetChanged();
            }
        });
        mInstrumentation.waitForIdleSync();

        final View newItem = listView.getChildAt(1);
        final CharSequence newText = ((TextView) newItem.findViewById(android.R.id.text1))
                .getText();

        Assert.assertTrue(newItem.hasTransientState());
        Assert.assertEquals(oldText, newText);
        Assert.assertEquals(tag, newItem.getTag());
    }

    private static class StableArrayAdapter<T> extends ArrayAdapter<T> {
        public StableArrayAdapter(Context context, int resource, List<T> objects) {
            super(context, resource, objects);
        }

        @Override
        public long getItemId(int position) {
            return getItem(position).hashCode();
        }

        @Override
        public boolean hasStableIds() {
            return true;
        }
    }
}
