001/*
002 * ModeShape (http://www.modeshape.org)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *       http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.modeshape.common.collection;
017
018import static org.hamcrest.core.Is.is;
019import static org.junit.Assert.assertThat;
020import static org.hamcrest.CoreMatchers.hasItems;
021import java.util.ArrayList;
022import java.util.Collections;
023import java.util.Iterator;
024import java.util.List;
025import java.util.ListIterator;
026import org.junit.Before;
027import org.junit.Test;
028
029/**
030 * @author Randall Hauch
031 */
032public class ImmutableAppendedListTest {
033
034    private List<String> list;
035    private List<String> parent;
036    private String[] data;
037
038    @Before
039    public void beforeEach() {
040        data = new String[] {"a", "b", "c", "d", "e"};
041        parent = new ArrayList<String>(5);
042        for (int i = 0; i != 4; ++i) {
043            parent.add(data[i]);
044        }
045        list = new ImmutableAppendedList<String>(parent, data[4]);
046    }
047
048    @Test( expected = IllegalArgumentException.class )
049    public void shouldNotAllowCreatingWithNullParentList() {
050        list = new ImmutableAppendedList<String>(null, data[4]);
051    }
052
053    @Test
054    public void shouldAllowCreatingWithEmptyParentList() {
055        data = new String[] {data[0], data[1]};
056        parent = Collections.singletonList(data[0]);
057        list = new ImmutableAppendedList<String>(parent, data[1]);
058        assertThat(list, hasItems(data));
059        assertThat(list.size(), is(parent.size() + 1));
060        assertThat(list.toArray(), is((Object[])data));
061        assertThat(list.toArray(new String[list.size()]), is(data));
062        assertThat(list.toArray(new String[list.size() - 1]), is(data)); // too small
063        assertThat(list.isEmpty(), is(false));
064    }
065
066    @Test
067    public void shouldAllowCreatingAppendedListWithNullForFinalElement() {
068        data[4] = null;
069        list = new ImmutableAppendedList<String>(parent, data[4]);
070        assertThat(list, hasItems(data));
071    }
072
073    @Test
074    public void shouldHaveSizeOfParentPlusOne() {
075        assertThat(list.size(), is(parent.size() + 1));
076    }
077
078    @Test
079    public void shouldConvertToArrayContainingAllValues() {
080        assertThat(list.toArray(), is((Object[])data));
081    }
082
083    @Test
084    public void shouldConvertToSuppliedArrayContainingAllValues() {
085        assertThat(list.toArray(new String[list.size()]), is(data));
086    }
087
088    @Test
089    public void shouldConvertToTooSmallSuppliedArrayContainingAllValues() {
090        assertThat(list.toArray(new String[list.size() - 1]), is(data));
091    }
092
093    @Test
094    public void shouldIterateOverAllValues() {
095        Iterator<String> iter = list.iterator();
096        int i = 0;
097        while (iter.hasNext()) {
098            assertThat(iter.next(), is(data[i++]));
099        }
100    }
101
102    @Test
103    public void shouldIterateOverAllValuesUsingListIterator() {
104        List<String> copy = new ArrayList<String>(list);
105        assertThat(copy.size(), is(list.size()));
106        ListIterator<String> listIter = list.listIterator();
107        ListIterator<String> copyIter = copy.listIterator();
108        for (int i = 0; i != 3; ++i) {
109            assertThat(listIter.hasPrevious(), is(false));
110            assertThat(copyIter.hasPrevious(), is(false));
111            while (listIter.hasNext()) {
112                assertThat(listIter.next(), is(copyIter.next()));
113            }
114            assertThat(listIter.hasNext(), is(false));
115            assertThat(copyIter.hasNext(), is(false));
116            while (listIter.hasPrevious()) {
117                assertThat(listIter.previous(), is(copyIter.previous()));
118            }
119        }
120        assertThat(listIter.hasPrevious(), is(false));
121        assertThat(copyIter.hasPrevious(), is(false));
122    }
123
124    @Test
125    public void shouldIterateBackwardsOverAllValuesUsingListIterator() {
126        List<String> copy = new ArrayList<String>(list);
127        assertThat(copy.size(), is(list.size()));
128        ListIterator<String> listIter = list.listIterator(list.size());
129        ListIterator<String> copyIter = copy.listIterator(copy.size());
130        assertThat(listIter.hasNext(), is(false));
131        assertThat(copyIter.hasNext(), is(false));
132        while (listIter.hasPrevious()) {
133            assertThat(listIter.previous(), is(copyIter.previous()));
134        }
135        assertThat(listIter.hasPrevious(), is(false));
136        assertThat(copyIter.hasPrevious(), is(false));
137    }
138
139    @Test( expected = UnsupportedOperationException.class )
140    public void shouldNotAllowAddingAnElement() {
141        list.add(null);
142    }
143
144    @Test( expected = UnsupportedOperationException.class )
145    public void shouldNotAllowAddingAnElementByIndex() {
146        list.add(0, null);
147    }
148
149    @Test( expected = UnsupportedOperationException.class )
150    public void shouldNotAllowAddingACollection() {
151        list.addAll(parent);
152    }
153
154    @Test( expected = UnsupportedOperationException.class )
155    public void shouldNotAllowAddingACollectionWithIndex() {
156        list.addAll(1, parent);
157    }
158
159    @Test( expected = UnsupportedOperationException.class )
160    public void shouldNotAllowRemovingAnElement() {
161        list.remove(null);
162    }
163
164    @Test( expected = UnsupportedOperationException.class )
165    public void shouldNotAllowRemovingAnElementByIndex() {
166        list.remove(0);
167    }
168
169    @Test( expected = UnsupportedOperationException.class )
170    public void shouldNotAllowRemovingAllElementsInACollection() {
171        list.removeAll(null);
172    }
173
174    @Test( expected = UnsupportedOperationException.class )
175    public void shouldNotAllowRetainingAllElementsInACollection() {
176        list.retainAll(null);
177    }
178
179    @Test( expected = UnsupportedOperationException.class )
180    public void shouldNotAllowSettingElementByIndex() {
181        list.set(0, null);
182    }
183
184    @Test( expected = UnsupportedOperationException.class )
185    public void shouldNotAllowClearingList() {
186        list.clear();
187    }
188
189    @Test
190    public void shouldReturnSameHashCodeMultipleTimes() {
191        int hc = list.hashCode();
192        for (int i = 0; i != 100; ++i) {
193            assertThat(list.hashCode(), is(hc));
194        }
195    }
196
197    @Test
198    public void shouldReturnSameHashCodeAsEquivalentArrayList() {
199        List<String> copy = new ArrayList<String>(list);
200        assertThat(list.hashCode(), is(copy.hashCode()));
201    }
202
203    @Test
204    public void shouldBeEqualToEquivalentArrayList() {
205        List<String> copy = new ArrayList<String>(list);
206        assertThat(list.equals(copy), is(true));
207    }
208
209    @Test
210    public void shouldHaveToStringThatIsTheSameAsEquivalentArrayList() {
211        List<String> copy = new ArrayList<String>(list);
212        assertThat(list.toString(), is(copy.toString()));
213    }
214
215    @Test
216    public void shouldFindLastIndexOfEachValue() {
217        for (int i = 0; i != data.length; ++i) {
218            String value = data[i];
219            int lastIndex = list.lastIndexOf(value);
220            assertThat(lastIndex, is(i));
221        }
222    }
223
224    @Test
225    public void shouldNotFindLastIndexOfValuesThatAreNotInList() {
226        assertThat(list.lastIndexOf("not found"), is(-1));
227        assertThat(list.lastIndexOf(null), is(-1));
228    }
229
230    @Test
231    public void shouldFindIndexOfEachValue() {
232        for (int i = 0; i != data.length; ++i) {
233            String value = data[i];
234            int lastIndex = list.lastIndexOf(value);
235            assertThat(lastIndex, is(i));
236        }
237    }
238
239    @Test
240    public void shouldNotFindIndexOfValuesThatAreNotInList() {
241        assertThat(list.lastIndexOf("not found"), is(-1));
242        assertThat(list.lastIndexOf(null), is(-1));
243    }
244
245    @Test
246    public void shouldGetValuesByIndex() {
247        for (int i = 0; i != data.length; ++i) {
248            String expectedValue = data[i];
249            String actualValue = list.get(i);
250            assertThat(actualValue, is(expectedValue));
251        }
252    }
253
254    @Test
255    public void shouldContainEachValue() {
256        for (int i = 0; i != data.length; ++i) {
257            String value = data[i];
258            assertThat(list.contains(value), is(true));
259        }
260    }
261
262    @Test
263    public void shouldNotContainValuesThatAreNotInList() {
264        assertThat(list.contains("not found"), is(false));
265        assertThat(list.contains(null), is(false));
266    }
267
268    @Test
269    public void shouldContainAllValuesInDuplicateCollection() {
270        List<String> copy = new ArrayList<String>(list);
271        assertThat(list.containsAll(copy), is(true));
272        assertThat(copy.containsAll(list), is(true));
273    }
274
275    @Test
276    public void shouldNeverBeEmpty() {
277        assertThat(list.isEmpty(), is(false));
278    }
279
280}