1/*
2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * @test
26 * @run testng UnmodifiableMapEntrySet
27 * @summary Unit tests for wrapping classes should delegate to default methods
28 */
29
30import java.util.ArrayList;
31import java.util.Collections;
32import java.util.HashMap;
33import java.util.List;
34import java.util.Map;
35import java.util.Spliterator;
36import java.util.TreeMap;
37import java.util.function.Consumer;
38import java.util.function.Function;
39import java.util.function.Supplier;
40
41import org.testng.annotations.Test;
42import org.testng.annotations.DataProvider;
43
44import static org.testng.Assert.assertEquals;
45
46@Test(groups = "unit")
47public class UnmodifiableMapEntrySet {
48    static Object[][] collections;
49
50    static <M extends Map<Integer, Integer>> M fillMap(int size, M m) {
51        for (int i = 0; i < size; i++) {
52            m.put(i, i);
53        }
54        return m;
55    }
56
57    @DataProvider(name="maps")
58    static Object[][] mapCases() {
59        if (collections != null) {
60            return collections;
61        }
62
63        List<Object[]> cases = new ArrayList<>();
64        for (int size : new int[] {1, 2, 16}) {
65            cases.add(new Object[] {
66                    String.format("new HashMap(%d)", size),
67                    (Supplier<Map<Integer, Integer>>)
68                    () -> Collections.unmodifiableMap(fillMap(size, new HashMap<>())) });
69            cases.add(new Object[] {
70                    String.format("new TreeMap(%d)", size),
71                    (Supplier<Map<Integer, Integer>>)
72                    () -> Collections.unmodifiableSortedMap(fillMap(size, new TreeMap<>())) });
73        }
74
75        return cases.toArray(new Object[0][]);
76    }
77
78    static class EntryConsumer implements Consumer<Map.Entry<Integer, Integer>> {
79        int updates;
80        @Override
81        public void accept(Map.Entry<Integer, Integer> me) {
82            try {
83                me.setValue(Integer.MAX_VALUE);
84                updates++;
85            } catch (UnsupportedOperationException e) {
86            }
87        }
88
89        void assertNoUpdates() {
90            assertEquals(updates, 0, "Updates to entries");
91        }
92    }
93
94    void testWithEntryConsumer(Consumer<EntryConsumer> c) {
95        EntryConsumer ec = new EntryConsumer();
96        c.accept(ec);
97        ec.assertNoUpdates();
98    }
99
100    @Test(dataProvider = "maps")
101    public void testForEach(String d, Supplier<Map<Integer, Integer>> ms) {
102        testWithEntryConsumer(
103                ec -> ms.get().entrySet().forEach(ec));
104    }
105
106    @Test(dataProvider = "maps")
107    public void testIteratorForEachRemaining(String d, Supplier<Map<Integer, Integer>> ms) {
108        testWithEntryConsumer(
109                ec -> ms.get().entrySet().iterator().forEachRemaining(ec));
110    }
111
112    @Test(dataProvider = "maps")
113    public void testIteratorNext(String d, Supplier<Map<Integer, Integer>> ms) {
114        testWithEntryConsumer(ec -> {
115            for (Map.Entry<Integer, Integer> me : ms.get().entrySet()) {
116                ec.accept(me);
117            }
118        });
119    }
120
121    @Test(dataProvider = "maps")
122    public void testSpliteratorForEachRemaining(String d, Supplier<Map<Integer, Integer>> ms) {
123        testSpliterator(
124                ms.get().entrySet()::spliterator,
125                // Higher order function returning a consumer that
126                // traverses all spliterator elements using an EntryConsumer
127                s -> ec -> s.forEachRemaining(ec));
128    }
129
130    @Test(dataProvider = "maps")
131    public void testSpliteratorTryAdvance(String d, Supplier<Map<Integer, Integer>> ms) {
132        testSpliterator(
133                ms.get().entrySet()::spliterator,
134                // Higher order function returning a consumer that
135                // traverses all spliterator elements using an EntryConsumer
136                s -> ec -> { while (s.tryAdvance(ec)); });
137    }
138
139    void testSpliterator(Supplier<Spliterator<Map.Entry<Integer, Integer>>> ss,
140                         // Higher order function that given a spliterator returns a
141                         // consumer for that spliterator which traverses elements
142                         // using an EntryConsumer
143                         Function<Spliterator<Map.Entry<Integer, Integer>>, Consumer<EntryConsumer>> sc) {
144        testWithEntryConsumer(sc.apply(ss.get()));
145
146        Spliterator<Map.Entry<Integer, Integer>> s = ss.get();
147        Spliterator<Map.Entry<Integer, Integer>> split = s.trySplit();
148        if (split != null) {
149            testWithEntryConsumer(sc.apply(split));
150            testWithEntryConsumer(sc.apply(s));
151        }
152    }
153
154    @Test(dataProvider = "maps")
155    public void testStreamForEach(String d, Supplier<Map<Integer, Integer>> ms) {
156        testWithEntryConsumer(ec -> ms.get().entrySet().stream().forEach(ec));
157    }
158
159    @Test(dataProvider = "maps")
160    public void testParallelStreamForEach(String d, Supplier<Map<Integer, Integer>> ms) {
161        testWithEntryConsumer(ec -> ms.get().entrySet().parallelStream().forEach(ec));
162    }
163}
164
165