1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.tests.java.util;
19
20import java.util.AbstractList;
21import java.util.ArrayList;
22import java.util.Arrays;
23import java.util.ConcurrentModificationException;
24import java.util.Iterator;
25import java.util.LinkedList;
26import java.util.List;
27import java.util.ListIterator;
28import java.util.NoSuchElementException;
29import java.util.RandomAccess;
30
31public class AbstractListTest extends junit.framework.TestCase {
32
33    static class SimpleList extends AbstractList {
34        ArrayList arrayList;
35
36        SimpleList() {
37            this.arrayList = new ArrayList();
38        }
39
40        public Object get(int index) {
41            return this.arrayList.get(index);
42        }
43
44        public void add(int i, Object o) {
45            this.arrayList.add(i, o);
46        }
47
48        public Object remove(int i) {
49            return this.arrayList.remove(i);
50        }
51
52        public int size() {
53            return this.arrayList.size();
54        }
55    }
56
57    /**
58     * java.util.AbstractList#hashCode()
59     */
60    public void test_hashCode() {
61        List list = new ArrayList();
62        list.add(new Integer(3));
63        list.add(new Integer(15));
64        list.add(new Integer(5));
65        list.add(new Integer(1));
66        list.add(new Integer(7));
67        int hashCode = 1;
68        Iterator i = list.iterator();
69        while (i.hasNext()) {
70            Object obj = i.next();
71            hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
72        }
73        assertTrue("Incorrect hashCode returned.  Wanted: " + hashCode
74                + " got: " + list.hashCode(), hashCode == list.hashCode());
75    }
76
77    /**
78     * java.util.AbstractList#iterator()
79     */
80    public void test_iterator() {
81        SimpleList list = new SimpleList();
82        list.add(new Object());
83        list.add(new Object());
84        Iterator it = list.iterator();
85        it.next();
86        it.remove();
87        it.next();
88    }
89
90    /**
91     * java.util.AbstractList#listIterator()
92     */
93    public void test_listIterator() {
94        Integer tempValue;
95        List list = new ArrayList();
96        list.add(new Integer(3));
97        list.add(new Integer(15));
98        list.add(new Integer(5));
99        list.add(new Integer(1));
100        list.add(new Integer(7));
101        ListIterator lit = list.listIterator();
102        assertTrue("Should not have previous", !lit.hasPrevious());
103        assertTrue("Should have next", lit.hasNext());
104        tempValue = (Integer) lit.next();
105        assertTrue("next returned wrong value.  Wanted 3, got: " + tempValue,
106                tempValue.intValue() == 3);
107        tempValue = (Integer) lit.previous();
108
109        SimpleList list2 = new SimpleList();
110        list2.add(new Object());
111        ListIterator lit2 = list2.listIterator();
112        lit2.add(new Object());
113        lit2.next();
114
115        //Regression test for Harmony-5808
116        list = new MockArrayList();
117        ListIterator it = list.listIterator();
118        it.add("one");
119        it.add("two");
120        assertEquals(2, list.size());
121    }
122
123    /**
124     * java.util.AbstractList#subList(int, int)
125     */
126    public void test_subListII() {
127        // Test each of the SubList operations to ensure a
128        // ConcurrentModificationException does not occur on an AbstractList
129        // which does not update modCount
130        SimpleList mList = new SimpleList();
131        mList.add(new Object());
132        mList.add(new Object());
133        List sList = mList.subList(0, 2);
134        sList.add(new Object()); // calls add(int, Object)
135        sList.get(0);
136
137        sList.add(0, new Object());
138        sList.get(0);
139
140        sList.addAll(Arrays.asList(new String[] { "1", "2" }));
141        sList.get(0);
142
143        sList.addAll(0, Arrays.asList(new String[] { "3", "4" }));
144        sList.get(0);
145
146        sList.remove(0);
147        sList.get(0);
148
149        ListIterator lit = sList.listIterator();
150        lit.add(new Object());
151        lit.next();
152        lit.remove();
153        lit.next();
154
155        sList.clear(); // calls removeRange()
156        sList.add(new Object());
157
158        // test the type of sublist that is returned
159        List al = new ArrayList();
160        for (int i = 0; i < 10; i++) {
161            al.add(new Integer(i));
162        }
163        assertTrue(
164                "Sublist returned should have implemented Random Access interface",
165                al.subList(3, 7) instanceof RandomAccess);
166
167        List ll = new LinkedList();
168        for (int i = 0; i < 10; i++) {
169            ll.add(new Integer(i));
170        }
171        assertTrue(
172                "Sublist returned should not have implemented Random Access interface",
173                !(ll.subList(3, 7) instanceof RandomAccess));
174
175    }
176
177    /**
178     * java.util.AbstractList#subList(int, int)
179     */
180    public void test_subList_empty() {
181        // Regression for HARMONY-389
182        List al = new ArrayList();
183        al.add("one");
184        List emptySubList = al.subList(0, 0);
185
186        try {
187            emptySubList.get(0);
188            fail("emptySubList.get(0) should throw IndexOutOfBoundsException");
189        } catch (IndexOutOfBoundsException e) {
190            // expected
191        }
192
193        try {
194            emptySubList.set(0, "one");
195            fail("emptySubList.set(0,Object) should throw IndexOutOfBoundsException");
196        } catch (IndexOutOfBoundsException e) {
197            // expected
198        }
199
200        try {
201            emptySubList.remove(0);
202            fail("emptySubList.remove(0) should throw IndexOutOfBoundsException");
203        } catch (IndexOutOfBoundsException e) {
204            // expected
205        }
206    }
207
208    class MockArrayList<E> extends AbstractList<E> {
209        /**
210         *
211         */
212        private static final long serialVersionUID = 1L;
213
214        ArrayList<E> list = new ArrayList<E>();
215
216        public E remove(int idx) {
217            modCount++;
218            return list.remove(idx);
219        }
220
221        @Override
222        public E get(int index) {
223            return list.get(index);
224        }
225
226        @Override
227        public int size() {
228            return list.size();
229        }
230
231        public void add(int idx, E o) {
232            modCount += 10;
233            list.add(idx, o);
234        }
235    }
236
237    /*
238    * Regression test for HY-4398
239    */
240    public void test_iterator_next() {
241        MockArrayList<String> t = new MockArrayList<String>();
242        t.list.add("a");
243        t.list.add("b");
244
245        Iterator it = t.iterator();
246
247        while (it.hasNext()) {
248            it.next();
249        }
250        try {
251            it.next();
252            fail("Should throw NoSuchElementException");
253        } catch (NoSuchElementException cme) {
254            // expected
255        }
256
257        t.add("c");
258        try {
259            it.remove();
260            fail("Should throw NoSuchElementException");
261        } catch (ConcurrentModificationException cme) {
262            // expected
263        }
264
265        it = t.iterator();
266        try {
267            it.remove();
268            fail("Should throw IllegalStateException");
269        } catch (IllegalStateException ise) {
270            // expected
271        }
272
273        Object value = it.next();
274        assertEquals("a", value);
275    }
276
277    /**
278     * java.util.AbstractList#subList(int, int)
279     */
280    public void test_subList_addAll() {
281        // Regression for HARMONY-390
282        List mainList = new ArrayList();
283        Object[] mainObjects = { "a", "b", "c" };
284        mainList.addAll(Arrays.asList(mainObjects));
285        List subList = mainList.subList(1, 2);
286        assertFalse("subList should not contain \"a\"", subList.contains("a"));
287        assertFalse("subList should not contain \"c\"", subList.contains("c"));
288        assertTrue("subList should contain \"b\"", subList.contains("b"));
289
290        Object[] subObjects = { "one", "two", "three" };
291        subList.addAll(Arrays.asList(subObjects));
292        assertFalse("subList should not contain \"a\"", subList.contains("a"));
293        assertFalse("subList should not contain \"c\"", subList.contains("c"));
294
295        Object[] expected = { "b", "one", "two", "three" };
296        ListIterator iter = subList.listIterator();
297        for (int i = 0; i < expected.length; i++) {
298            assertTrue("subList should contain " + expected[i], subList
299                    .contains(expected[i]));
300            assertTrue("should be more elements", iter.hasNext());
301            assertEquals("element in incorrect position", expected[i], iter
302                    .next());
303        }
304    }
305
306    public void test_indexOfLjava_lang_Object() {
307        AbstractList al = new ArrayList();
308        al.add(0);
309        al.add(1);
310        al.add(2);
311        al.add(3);
312        al.add(4);
313
314        assertEquals(-1, al.indexOf(5));
315        assertEquals(2, al.indexOf(2));
316    }
317
318    public void test_lastIndexOfLjava_lang_Object() {
319        AbstractList al = new ArrayList();
320        al.add(0);
321        al.add(1);
322        al.add(2);
323        al.add(2);
324        al.add(2);
325        al.add(2);
326        al.add(2);
327        al.add(3);
328        al.add(4);
329
330        assertEquals(-1, al.lastIndexOf(5));
331        assertEquals(6, al.lastIndexOf(2));
332    }
333
334    public void test_listIteratorI() {
335        AbstractList al1 = new ArrayList();
336        AbstractList al2 = new ArrayList();
337        al1.add(0);
338        al1.add(1);
339        al1.add(2);
340        al1.add(3);
341        al1.add(4);
342        al2.add(2);
343        al2.add(3);
344        al2.add(4);
345
346        Iterator li1 = al1.listIterator(2);
347        Iterator li2 = al2.listIterator();
348
349        while(li1.hasNext()&&li2.hasNext()) {
350            assertEquals(li1.next(), li2.next());
351        }
352        assertSame(li1.hasNext(),li2.hasNext());
353
354        try {
355            al1.listIterator(-1);
356            fail("IndexOutOfBoundsException expected");
357        } catch (IndexOutOfBoundsException ee) {
358            //expected
359        }
360
361        try {
362            al1.listIterator(al1.size() + 1);
363            fail("IndexOutOfBoundsException expected");
364        } catch (IndexOutOfBoundsException ee) {
365            //expected
366        }
367    }
368
369    protected void doneSuite() {
370    }
371
372    class MockRemoveFailureArrayList<E> extends AbstractList<E> {
373
374        @Override
375        public E get(int location) {
376            // TODO Auto-generated method stub
377            return null;
378        }
379
380        @Override
381        public int size() {
382            // TODO Auto-generated method stub
383            return 0;
384        }
385
386        public E remove(int idx) {
387            modCount += 2;
388            return null;
389        }
390
391        public int getModCount() {
392            return modCount;
393        }
394    }
395
396    //test remove for failure by inconsistency of modCount and expectedModCount
397    public void test_remove() {
398        MockRemoveFailureArrayList<String> mrfal = new MockRemoveFailureArrayList<String>();
399        Iterator<String> imrfal = mrfal.iterator();
400        imrfal.next();
401        imrfal.remove();
402        try {
403            imrfal.remove();
404        } catch (ConcurrentModificationException e) {
405            fail("Excepted to catch IllegalStateException not ConcurrentModificationException");
406        } catch (IllegalStateException e) {
407            //Excepted to catch IllegalStateException here
408        }
409    }
410
411    public void test_subListII2() {
412        List<Integer> holder = new ArrayList<Integer>(16);
413        for (int i = 0; i < 10; i++) {
414            holder.add(i);
415        }
416
417        // parent change should cause sublist concurrentmodification fail
418        List<Integer> sub = holder.subList(0, holder.size());
419        holder.add(11);
420        try {
421            sub.size();
422            fail("Should throw ConcurrentModificationException.");
423        } catch (ConcurrentModificationException e) {
424        }
425        try {
426            sub.add(12);
427            fail("Should throw ConcurrentModificationException.");
428        } catch (ConcurrentModificationException e) {
429        }
430        try {
431            sub.add(0, 11);
432            fail("Should throw ConcurrentModificationException.");
433        } catch (ConcurrentModificationException e) {
434        }
435        try {
436            sub.clear();
437            fail("Should throw ConcurrentModificationException.");
438        } catch (ConcurrentModificationException e) {
439        }
440        try {
441            sub.contains(11);
442            fail("Should throw ConcurrentModificationException.");
443        } catch (ConcurrentModificationException e) {
444        }
445        try {
446            sub.get(9);
447            fail("Should throw ConcurrentModificationException.");
448        } catch (ConcurrentModificationException e) {
449        }
450        try {
451            sub.indexOf(10);
452            fail("Should throw ConcurrentModificationException.");
453        } catch (ConcurrentModificationException e) {
454        }
455        try {
456            sub.isEmpty();
457            fail("Should throw ConcurrentModificationException.");
458        } catch (ConcurrentModificationException e) {
459        }
460        try {
461            sub.iterator();
462            fail("Should throw ConcurrentModificationException.");
463        } catch (ConcurrentModificationException e) {
464        }
465        try {
466            sub.lastIndexOf(10);
467            fail("Should throw ConcurrentModificationException.");
468        } catch (ConcurrentModificationException e) {
469        }
470        try {
471            sub.listIterator();
472            fail("Should throw ConcurrentModificationException.");
473        } catch (ConcurrentModificationException e) {
474        }
475        try {
476            sub.listIterator(0);
477            fail("Should throw ConcurrentModificationException.");
478        } catch (ConcurrentModificationException e) {
479        }
480        try {
481            sub.remove(0);
482            fail("Should throw ConcurrentModificationException.");
483        } catch (ConcurrentModificationException e) {
484        }
485        try {
486            sub.remove(9);
487            fail("Should throw ConcurrentModificationException.");
488        } catch (ConcurrentModificationException e) {
489        }
490        try {
491            sub.set(0, 0);
492            fail("Should throw ConcurrentModificationException.");
493        } catch (ConcurrentModificationException e) {
494        }
495        try {
496            sub.size();
497            fail("Should throw ConcurrentModificationException.");
498        } catch (ConcurrentModificationException e) {
499        }
500        try {
501            sub.toArray();
502            fail("Should throw ConcurrentModificationException.");
503        } catch (ConcurrentModificationException e) {
504        }
505        try {
506            sub.toString();
507            fail("Should throw ConcurrentModificationException.");
508        } catch (ConcurrentModificationException e) {
509        }
510
511        holder.clear();
512    }
513
514    public void test_indexOf_Ljava_lang_Object() {
515        AbstractList<Integer> list = new MockArrayList<Integer>();
516        Integer[] array = { 1, 2, 3, 4, 5 };
517        list.addAll(Arrays.asList(array));
518
519        assertEquals("find 0 in the list do not contain 0", -1, list
520                .indexOf(new Integer(0)));
521        assertEquals("did not return the right location of element 3", 2, list
522                .indexOf(new Integer(3)));
523        assertEquals("find null in the list do not contain null element", -1,
524                list.indexOf(null));
525        list.add(null);
526        assertEquals("did not return the right location of element null", 5,
527                list.indexOf(null));
528    }
529
530    public void test_lastIndexOf_Ljava_lang_Object() {
531        AbstractList<Integer> list = new MockArrayList<Integer>();
532        Integer[] array = { 1, 2, 3, 4, 5, 5, 4, 3, 2, 1 };
533        list.addAll(Arrays.asList(array));
534
535        assertEquals("find 6 in the list do not contain 6", -1, list
536                .lastIndexOf(new Integer(6)));
537        assertEquals("did not return the right location of element 4", 6, list
538                .lastIndexOf(new Integer(4)));
539        assertEquals("find null in the list do not contain null element", -1,
540                list.lastIndexOf(null));
541        list.add(null);
542        assertEquals("did not return the right location of element null", 10,
543                list.lastIndexOf(null));
544    }
545
546    public void test_remove_I() {
547        class MockList<E> extends AbstractList<E> {
548            private ArrayList<E> list;
549
550            @Override
551            public E get(int location) {
552                return list.get(location);
553            }
554
555            @Override
556            public int size() {
557                return list.size();
558            }
559
560        }
561        AbstractList<Integer> list = new MockList<Integer>();
562        try {
563            list.remove(0);
564            fail("should throw UnsupportedOperationException");
565        } catch (UnsupportedOperationException e) {
566            // expected
567        }
568
569        try {
570            list.set(0, null);
571            fail("should throw UnsupportedOperationException");
572        } catch (UnsupportedOperationException e) {
573            // expected
574        }
575    }
576}
577