New CTS ExpandableListView tests moved from framework.

The CTS tests were duplicates of the ones in framework, and were missing
some recent additions. Everything has been merged in CTS.

Change-Id: I735d87b4aaa750b76da24ece3d684f126b831fe8
http://b/issue?id=2541389
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListTester.java b/tests/tests/widget/src/android/widget/cts/ExpandableListTester.java
new file mode 100644
index 0000000..8175807
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListTester.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2007 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 android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.ExpandableListAdapter;
+import android.widget.ExpandableListView;
+import android.widget.cts.util.ExpandableListScenario;
+import android.widget.cts.util.ListUtil;
+
+import junit.framework.Assert;
+
+public class ExpandableListTester {
+    private final ExpandableListView mExpandableListView;
+    private final ExpandableListAdapter mAdapter;
+    private final ListUtil mListUtil;
+
+    private final ActivityInstrumentationTestCase2<? extends ExpandableListScenario>
+        mActivityInstrumentation;
+
+    Instrumentation mInstrumentation;
+
+    public ExpandableListTester(
+            ExpandableListView expandableListView,
+            ActivityInstrumentationTestCase2<? extends ExpandableListScenario>
+            activityInstrumentation) {
+        mExpandableListView = expandableListView;
+        Instrumentation instrumentation = activityInstrumentation.getInstrumentation();
+        mListUtil = new ListUtil(mExpandableListView, instrumentation);
+        mAdapter = mExpandableListView.getExpandableListAdapter();
+        mActivityInstrumentation = activityInstrumentation;
+        mInstrumentation = mActivityInstrumentation.getInstrumentation();
+    }
+
+    private void expandGroup(final int groupIndex, int flatPosition) {
+        Assert.assertFalse("Group is already expanded", mExpandableListView
+                .isGroupExpanded(groupIndex));
+        mListUtil.arrowScrollToSelectedPosition(flatPosition);
+        mInstrumentation.waitForIdleSync();
+        mActivityInstrumentation.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        mActivityInstrumentation.getInstrumentation().waitForIdleSync();
+        Assert.assertTrue("Group did not expand " + groupIndex, 
+                mExpandableListView.isGroupExpanded(groupIndex));
+    }
+
+    void testContextMenus() {
+        // Add a position tester ContextMenu listener to the ExpandableListView
+        PositionTesterContextMenuListener menuListener = new PositionTesterContextMenuListener();
+        mExpandableListView.setOnCreateContextMenuListener(menuListener);
+
+        int index = 0;
+
+        // Scrolling on header elements should trigger an AdapterContextMenu
+        for (int i=0; i<mExpandableListView.getHeaderViewsCount(); i++) {
+            // Check group index in context menu
+            menuListener.expectAdapterContextMenu(i);
+            // Make sure the group is visible so that getChild finds it
+            mListUtil.arrowScrollToSelectedPosition(index);
+            View headerChild = mExpandableListView.getChildAt(index
+                    - mExpandableListView.getFirstVisiblePosition());
+            mExpandableListView.showContextMenuForChild(headerChild);
+            mInstrumentation.waitForIdleSync();
+            Assert.assertNull(menuListener.getErrorMessage(), menuListener.getErrorMessage());
+            index++;
+        }
+
+        int groupCount = mAdapter.getGroupCount();
+        for (int groupIndex = 0; groupIndex < groupCount; groupIndex++) {
+
+            // Expand group
+            expandGroup(groupIndex, index);
+
+            // Check group index in context menu
+            menuListener.expectGroupContextMenu(groupIndex);
+            // Make sure the group is visible so that getChild finds it
+            mListUtil.arrowScrollToSelectedPosition(index);
+            View groupChild = mExpandableListView.getChildAt(index
+                    - mExpandableListView.getFirstVisiblePosition());
+            mExpandableListView.showContextMenuForChild(groupChild);
+            mInstrumentation.waitForIdleSync();
+            Assert.assertNull(menuListener.getErrorMessage(), menuListener.getErrorMessage());
+            index++;
+
+            final int childrenCount = mAdapter.getChildrenCount(groupIndex);
+            for (int childIndex = 0; childIndex < childrenCount; childIndex++) {
+                // Check child index in context menu
+                mListUtil.arrowScrollToSelectedPosition(index);
+                menuListener.expectChildContextMenu(groupIndex, childIndex);
+                View child = mExpandableListView.getChildAt(index
+                        - mExpandableListView.getFirstVisiblePosition());
+                mExpandableListView.showContextMenuForChild(child);
+                mInstrumentation.waitForIdleSync();
+                Assert.assertNull(menuListener.getErrorMessage(), menuListener.getErrorMessage());
+                index++;
+            }
+        }
+
+        // Scrolling on footer elements should trigger an AdapterContextMenu
+        for (int i=0; i<mExpandableListView.getFooterViewsCount(); i++) {
+            // Check group index in context menu
+            menuListener.expectAdapterContextMenu(index);
+            // Make sure the group is visible so that getChild finds it
+            mListUtil.arrowScrollToSelectedPosition(index);
+            View footerChild = mExpandableListView.getChildAt(index
+                    - mExpandableListView.getFirstVisiblePosition());
+            mExpandableListView.showContextMenuForChild(footerChild);
+            mInstrumentation.waitForIdleSync();
+            Assert.assertNull(menuListener.getErrorMessage(), menuListener.getErrorMessage());
+            index++;
+        }
+
+        // Cleanup: remove the listener we added.
+        mExpandableListView.setOnCreateContextMenuListener(null);
+    }
+
+    private int expandAGroup() {
+        final int groupIndex = 2;
+        final int headerCount = mExpandableListView.getHeaderViewsCount();
+        Assert.assertTrue("Not enough groups", groupIndex < mAdapter.getGroupCount());
+        expandGroup(groupIndex, groupIndex + headerCount);
+        return groupIndex;
+    }
+
+    // This method assumes that NO group is expanded when called
+    void testConvertionBetweenFlatAndPackedOnGroups() {
+        final int headerCount = mExpandableListView.getHeaderViewsCount();
+
+        for (int i=0; i<headerCount; i++) {
+            Assert.assertEquals("Non NULL position for header item",
+                    ExpandableListView.PACKED_POSITION_VALUE_NULL,
+                    mExpandableListView.getExpandableListPosition(i));
+        }
+
+        // Test all (non expanded) groups
+        final int groupCount = mAdapter.getGroupCount();
+        for (int groupIndex = 0; groupIndex < groupCount; groupIndex++) {
+            int expectedFlatPosition = headerCount + groupIndex;
+            long packedPositionForGroup = ExpandableListView.getPackedPositionForGroup(groupIndex);
+            Assert.assertEquals("Group not found at flat position " + expectedFlatPosition,
+                    packedPositionForGroup,
+                    mExpandableListView.getExpandableListPosition(expectedFlatPosition));
+
+            Assert.assertEquals("Wrong flat position for group " + groupIndex,
+                    expectedFlatPosition,
+                    mExpandableListView.getFlatListPosition(packedPositionForGroup));
+        }
+
+        for (int i=0; i<mExpandableListView.getFooterViewsCount(); i++) {
+            Assert.assertEquals("Non NULL position for header item",
+                    ExpandableListView.PACKED_POSITION_VALUE_NULL,
+                    mExpandableListView.getExpandableListPosition(headerCount + groupCount + i));
+        }
+    }
+
+    // This method assumes that NO group is expanded when called
+    void testConvertionBetweenFlatAndPackedOnChildren() {
+        // Test with an expanded group
+        final int headerCount = mExpandableListView.getHeaderViewsCount();
+        final int groupIndex = expandAGroup();
+
+        final int childrenCount = mAdapter.getChildrenCount(groupIndex);
+        for (int childIndex = 0; childIndex < childrenCount; childIndex++) {
+            int expectedFlatPosition = headerCount + groupIndex + 1 + childIndex;
+            long childPos = ExpandableListView.getPackedPositionForChild(groupIndex, childIndex);
+
+            Assert.assertEquals("Wrong flat position for child ",
+                    childPos,
+                    mExpandableListView.getExpandableListPosition(expectedFlatPosition));
+
+            Assert.assertEquals("Wrong flat position for child ",
+                    expectedFlatPosition,
+                    mExpandableListView.getFlatListPosition(childPos));
+        }
+    }
+
+    // This method assumes that NO group is expanded when called
+    void testSelectedPositionOnGroups() {
+        int index = 0;
+
+        // Scrolling on header elements should not give a valid selected position.
+        for (int i=0; i<mExpandableListView.getHeaderViewsCount(); i++) {
+            mListUtil.arrowScrollToSelectedPosition(index);
+            Assert.assertEquals("Header item is selected",
+                    ExpandableListView.PACKED_POSITION_VALUE_NULL,
+                    mExpandableListView.getSelectedPosition());
+            index++;
+        }
+
+        // Check selection on group items
+        final int groupCount = mAdapter.getGroupCount();
+        for (int groupIndex = 0; groupIndex < groupCount; groupIndex++) {
+            mListUtil.arrowScrollToSelectedPosition(index);
+            Assert.assertEquals("Group item is not selected",
+                    ExpandableListView.getPackedPositionForGroup(groupIndex),
+                    mExpandableListView.getSelectedPosition());
+            index++;
+        }
+
+        // Scrolling on footer elements should not give a valid selected position.
+        for (int i=0; i<mExpandableListView.getFooterViewsCount(); i++) {
+            mListUtil.arrowScrollToSelectedPosition(index);
+            Assert.assertEquals("Footer item is selected",
+                    ExpandableListView.PACKED_POSITION_VALUE_NULL,
+                    mExpandableListView.getSelectedPosition());
+            index++;
+        }
+    }
+
+    // This method assumes that NO group is expanded when called
+    void testSelectedPositionOnChildren() {
+        // Test with an expanded group
+        final int headerCount = mExpandableListView.getHeaderViewsCount();
+        final int groupIndex = expandAGroup();
+
+        final int childrenCount = mAdapter.getChildrenCount(groupIndex);
+        for (int childIndex = 0; childIndex < childrenCount; childIndex++) {
+            int childFlatPosition = headerCount + groupIndex + 1 + childIndex;
+            mListUtil.arrowScrollToSelectedPosition(childFlatPosition);
+            Assert.assertEquals("Group item is not selected",
+                    ExpandableListView.getPackedPositionForChild(groupIndex, childIndex),
+                    mExpandableListView.getSelectedPosition());
+        }
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java b/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java
index c6c0b35..fc39364 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java
@@ -16,7 +16,10 @@
 
 package android.widget.cts;
 
-import java.util.List;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
 
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.MediumTest;
@@ -27,21 +30,19 @@
 import android.widget.cts.util.ExpandableListScenario;
 import android.widget.cts.util.ListUtil;
 import android.widget.cts.util.ExpandableListScenario.MyGroup;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestTargetNew;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
+
+import java.util.List;
 
 @TestTargetClass(ExpandableListView.class)
 public class ExpandableListViewBasicTest extends
         ActivityInstrumentationTestCase2<ExpandableListSimple> {
     private ExpandableListScenario mActivity;
-    private ExpandableListView mListView;
+    private ExpandableListView mExpandableListView;
     private ExpandableListAdapter mAdapter;
     private ListUtil mListUtil;
 
     public ExpandableListViewBasicTest() {
-        super("com.android.cts.stub", ExpandableListSimple.class);
+        super(ExpandableListSimple.class);
     }
 
     @Override
@@ -49,27 +50,27 @@
         super.setUp();
 
         mActivity = getActivity();
-        mListView = mActivity.getExpandableListView();
-        mAdapter = mListView.getExpandableListAdapter();
-        mListUtil = new ListUtil(mListView, getInstrumentation());
+        mExpandableListView = mActivity.getExpandableListView();
+        mAdapter = mExpandableListView.getExpandableListAdapter();
+        mListUtil = new ListUtil(mExpandableListView, getInstrumentation());
     }
 
     @MediumTest
     public void testPreconditions() {
         assertNotNull(mActivity);
-        assertNotNull(mListView);
+        assertNotNull(mExpandableListView);
     }
 
     private int expandGroup(int numChildren, boolean atLeastOneChild) {
         final int groupPos = mActivity.findGroupWithNumChildren(numChildren, atLeastOneChild);
 
         assertTrue("Could not find group to expand", groupPos >= 0);
-        assertFalse("Group is already expanded", mListView.isGroupExpanded(groupPos));
+        assertFalse("Group is already expanded", mExpandableListView.isGroupExpanded(groupPos));
         mListUtil.arrowScrollToSelectedPosition(groupPos);
         getInstrumentation().waitForIdleSync();
         sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
         getInstrumentation().waitForIdleSync();
-        assertTrue("Group did not expand", mListView.isGroupExpanded(groupPos));
+        assertTrue("Group did not expand", mExpandableListView.isGroupExpanded(groupPos));
 
         return groupPos;
     }
@@ -97,7 +98,7 @@
 
         sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
         getInstrumentation().waitForIdleSync();
-        assertFalse("Group did not collapse", mListView.isGroupExpanded(groupPos));
+        assertFalse("Group did not collapse", mExpandableListView.isGroupExpanded(groupPos));
     }
 
     @TestTargets({
@@ -122,13 +123,13 @@
         getInstrumentation().waitForIdleSync();
 
         // Ensure it expanded
-        assertTrue("Group did not expand", mListView.isGroupExpanded(0));
+        assertTrue("Group did not expand", mExpandableListView.isGroupExpanded(0));
 
         // Wait until that's all good
         getInstrumentation().waitForIdleSync();
 
         // Make sure it expanded
-        assertTrue("Group did not expand", mListView.isGroupExpanded(0));
+        assertTrue("Group did not expand", mExpandableListView.isGroupExpanded(0));
 
         // Insert a collapsed group in front of the one just expanded
         List<MyGroup> groups = mActivity.getGroups();
@@ -149,8 +150,28 @@
 
         // Make sure the right group is expanded
         assertTrue("The expanded state didn't stay with the proper group",
-                mListView.isGroupExpanded(1));
+                mExpandableListView.isGroupExpanded(1));
         assertFalse("The expanded state was given to the inserted group",
-                mListView.isGroupExpanded(0));
+                mExpandableListView.isGroupExpanded(0));
+    }
+
+    @MediumTest
+    public void testContextMenus() {
+        ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
+        tester.testContextMenus();
+    }
+
+    @MediumTest
+    public void testConvertionBetweenFlatAndPacked() {
+        ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
+        tester.testConvertionBetweenFlatAndPackedOnGroups();
+        tester.testConvertionBetweenFlatAndPackedOnChildren();
+    }
+
+    @MediumTest
+    public void testSelectedPosition() {
+        ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
+        tester.testSelectedPositionOnGroups();
+        tester.testSelectedPositionOnChildren();
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java b/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
index af420b4..5ab7f4d 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
@@ -519,10 +519,10 @@
         args = {int.class, int.class}
     )
     public void testGetPackedPositionForChild() {
-        assertEquals((long) 0x8000000000000000L,
+        assertEquals(0x8000000000000000L,
                 ExpandableListView.getPackedPositionForChild(0, 0));
 
-        assertEquals((long) 0xffffffffffffffffL,
+        assertEquals(0xffffffffffffffffL,
                 ExpandableListView.getPackedPositionForChild(Integer.MAX_VALUE, 0xffffffff));
     }
 
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java b/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java
index 57776a0..fe65f98 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java
@@ -16,16 +16,16 @@
 
 package android.widget.cts;
 
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.widget.ExpandableListView;
 import android.widget.cts.util.ListUtil;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestTargetNew;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
 
 @TestTargetClass(ExpandableListView.class)
 public class ExpandableListViewWithHeadersTest extends
@@ -34,7 +34,7 @@
     private ListUtil mListUtil;
 
     public ExpandableListViewWithHeadersTest() {
-        super("com.android.cts.stub", ExpandableListWithHeaders.class);
+        super(ExpandableListWithHeaders.class);
     }
 
     @Override
@@ -78,4 +78,24 @@
         getInstrumentation().waitForIdleSync();
         assertTrue(mExpandableListView.isGroupExpanded(0));
     }
+
+    @MediumTest
+    public void testContextMenus() {
+        ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
+        tester.testContextMenus();
+    }
+
+    @MediumTest
+    public void testConvertionBetweenFlatAndPacked() {
+        ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
+        tester.testConvertionBetweenFlatAndPackedOnGroups();
+        tester.testConvertionBetweenFlatAndPackedOnChildren();
+    }
+
+    @MediumTest
+    public void testSelectedPosition() {
+        ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
+        tester.testSelectedPositionOnGroups();
+        tester.testSelectedPositionOnChildren();
+    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/PositionTesterContextMenuListener.java b/tests/tests/widget/src/android/widget/cts/PositionTesterContextMenuListener.java
new file mode 100644
index 0000000..a1c9bc4
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/PositionTesterContextMenuListener.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010 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 android.view.ContextMenu;
+import android.view.View;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.View.OnCreateContextMenuListener;
+import android.widget.ExpandableListView;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+
+public class PositionTesterContextMenuListener implements OnCreateContextMenuListener {
+
+    private int groupPosition, childPosition;
+
+    // Fake constant to store in testType a test type specific to headers and footers
+    private static final int ADAPTER_TYPE = -1;
+    private int testType; // as returned by getPackedPositionType
+
+    // Will be set to null by each call to onCreateContextMenu, unless an error occurred. 
+    private String errorMessage;
+
+    public void expectGroupContextMenu(int groupPosition) {
+        this.groupPosition = groupPosition;
+        testType = ExpandableListView.PACKED_POSITION_TYPE_GROUP;
+    }
+
+    public void expectChildContextMenu(int groupPosition, int childPosition) {
+        this.groupPosition = groupPosition;
+        this.childPosition = childPosition;
+        testType = ExpandableListView.PACKED_POSITION_TYPE_CHILD;
+    }
+
+    public void expectAdapterContextMenu(int flatPosition) {
+        this.groupPosition = flatPosition;
+        testType = ADAPTER_TYPE;
+    }
+
+    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+        errorMessage = null;
+        if (testType == ADAPTER_TYPE) {
+            if (!isTrue("MenuInfo is not an AdapterContextMenuInfo",
+                    menuInfo instanceof AdapterContextMenuInfo)) {
+                return;
+            }
+            AdapterContextMenuInfo adapterContextMenuInfo = (AdapterContextMenuInfo) menuInfo;
+            if (!areEqual("Wrong flat position", groupPosition, adapterContextMenuInfo.position)) {
+                return;
+            }
+        } else {
+            if (!isTrue("MenuInfo is not an ExpandableListContextMenuInfo",
+                    menuInfo instanceof ExpandableListView.ExpandableListContextMenuInfo)) {
+                return;
+            }
+            ExpandableListView.ExpandableListContextMenuInfo elvMenuInfo =
+                (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
+            long packedPosition = elvMenuInfo.packedPosition;
+
+            int packedPositionType = ExpandableListView.getPackedPositionType(packedPosition);
+            if (!areEqual("Wrong packed position type", testType, packedPositionType)) {
+                return;
+            }
+
+            int packedPositionGroup = ExpandableListView.getPackedPositionGroup(packedPosition);
+            if (!areEqual("Wrong group position", groupPosition, packedPositionGroup)) {
+                return;
+            }
+
+            if (testType == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
+                int packedPositionChild = ExpandableListView.getPackedPositionChild(packedPosition);
+                if (!areEqual("Wrong child position", childPosition, packedPositionChild)) {
+                    return;
+                }
+            }
+        }
+    }
+
+    private boolean areEqual(String message, int expected, int actual) {
+        if (expected != actual) {
+            errorMessage = String.format(message + " (%d vs %d", expected, actual);
+            return false;
+        }
+        return true;
+    }
+
+    private boolean isTrue(String message, boolean value) {
+        if (!value) {
+            errorMessage = message;
+            return false;
+        }
+        return true;
+    }
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+}