1/*
2 * Copyright 2012, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 *     * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *     * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32package org.jf.util;
33
34import junit.framework.Assert;
35import org.junit.Before;
36import org.junit.Test;
37
38import javax.annotation.Nonnull;
39import java.util.Iterator;
40import java.util.List;
41import java.util.ListIterator;
42import java.util.NoSuchElementException;
43
44public class AbstractForwardSequentialListTest {
45    private List<Integer> list;
46
47    @Before
48    public void setup() {
49        list = new AbstractForwardSequentialList<Integer>() {
50            @Nonnull @Override public Iterator<Integer> iterator() {
51                return new Iterator<Integer>() {
52                    private int index = 0;
53
54                    @Override public boolean hasNext() {
55                        return index < 100;
56                    }
57
58                    @Override public Integer next() {
59                        if (!hasNext()) {
60                            throw new NoSuchElementException();
61                        }
62                        return index++;
63                    }
64
65                    @Override public void remove() {
66                        throw new UnsupportedOperationException();
67                    }
68                };
69            }
70
71            @Override public int size() {
72                return 100;
73            }
74        };
75    }
76
77    private void testForwardIterationImpl(ListIterator<Integer> iter) {
78        Assert.assertFalse(iter.hasPrevious());
79
80        for (int i=0; i<100; i++) {
81            Assert.assertEquals(i, iter.nextIndex());
82            Assert.assertEquals(i-1, iter.previousIndex());
83
84            Assert.assertTrue(iter.hasNext());
85
86            Assert.assertEquals(i, iter.next().intValue());
87            Assert.assertTrue(iter.hasPrevious());
88        }
89
90        Assert.assertFalse(iter.hasNext());
91        Assert.assertEquals(iter.nextIndex(), 100);
92        Assert.assertEquals(iter.previousIndex(), 99);
93    }
94
95    @Test
96    public void testForwardIteration() {
97        testForwardIterationImpl(list.listIterator());
98    }
99
100    private void testReverseIterationImpl(ListIterator<Integer> iter) {
101        Assert.assertFalse(iter.hasNext());
102
103        for (int i=99; i>=0; i--) {
104            Assert.assertEquals(i+1, iter.nextIndex());
105            Assert.assertEquals(i, iter.previousIndex());
106
107            Assert.assertTrue(iter.hasPrevious());
108
109            Assert.assertEquals(i, iter.previous().intValue());
110            Assert.assertTrue(iter.hasNext());
111        }
112
113        Assert.assertFalse(iter.hasPrevious());
114        Assert.assertEquals(0, iter.nextIndex());
115        Assert.assertEquals(-1, iter.previousIndex());
116    }
117
118    @Test
119    public void testReverseIteration() {
120        testReverseIterationImpl(list.listIterator(100));
121    }
122
123    @Test
124    public void testAlternatingIteration() {
125        ListIterator<Integer> iter = list.listIterator(50);
126
127        for (int i=0; i<10; i++) {
128            Assert.assertTrue(iter.hasNext());
129            Assert.assertTrue(iter.hasPrevious());
130            Assert.assertEquals(50, iter.nextIndex());
131            Assert.assertEquals(49, iter.previousIndex());
132
133            Assert.assertEquals(50, iter.next().intValue());
134
135            Assert.assertTrue(iter.hasNext());
136            Assert.assertTrue(iter.hasPrevious());
137            Assert.assertEquals(51, iter.nextIndex());
138            Assert.assertEquals(50, iter.previousIndex());
139
140            Assert.assertEquals(50, iter.previous().intValue());
141        }
142    }
143
144    @Test
145    public void testAlternatingIteration2() {
146        ListIterator<Integer> iter = list.listIterator(0);
147
148        for (int i=0; i<10; i++) {
149            testForwardIterationImpl(iter);
150            testReverseIterationImpl(iter);
151        }
152    }
153
154    @Test(expected = IndexOutOfBoundsException.class)
155    public void testNegativeIndex() {
156        list.listIterator(-1);
157    }
158
159    @Test(expected = IndexOutOfBoundsException.class)
160    public void testLargeIndex() {
161        list.listIterator(101);
162    }
163
164    @Test(expected = IndexOutOfBoundsException.class)
165    public void testLargeIndex2() {
166        list.listIterator(1000000);
167    }
168
169    @Test
170    public void testForwardIterationException() {
171        // note: no "expected = NoSuchElementException", because we want to make sure the exception occurs only during
172        // the last call to next()
173
174        ListIterator<Integer> iter = list.listIterator(0);
175        for (int i=0; i<100; i++) {
176            iter.next();
177        }
178        try {
179            iter.next();
180        } catch (NoSuchElementException ex) {
181            return;
182        }
183        Assert.fail();
184    }
185
186    @Test(expected = NoSuchElementException.class)
187    public void testForwardIterationException2() {
188        ListIterator<Integer> iter = list.listIterator(100);
189        iter.next();
190    }
191
192    @Test
193    public void testReverseIterationException() {
194        // note: no "expected = NoSuchElementException", because we want to make sure the exception occurs only during
195        // the last call to previous()
196
197        ListIterator<Integer> iter = list.listIterator(100);
198        for (int i=0; i<100; i++) {
199            iter.previous();
200        }
201        try {
202            iter.previous();
203        } catch (NoSuchElementException ex) {
204            return;
205        }
206        Assert.fail();
207    }
208
209    @Test(expected = NoSuchElementException.class)
210    public void testReverseIterationException2() {
211        ListIterator<Integer> iter = list.listIterator(0);
212        iter.previous();
213    }
214}
215