1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.lang3.tuple;
18
19 import static org.apache.commons.lang3.LangAssertions.assertNullPointerException;
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
22 import static org.junit.jupiter.api.Assertions.assertNotEquals;
23 import static org.junit.jupiter.api.Assertions.assertNull;
24 import static org.junit.jupiter.api.Assertions.assertTrue;
25
26 import java.util.AbstractMap;
27 import java.util.Calendar;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.LinkedHashMap;
31 import java.util.Map;
32 import java.util.Map.Entry;
33 import java.util.Objects;
34 import java.util.TreeMap;
35 import java.util.WeakHashMap;
36 import java.util.concurrent.ConcurrentHashMap;
37 import java.util.concurrent.ConcurrentSkipListMap;
38 import java.util.stream.Stream;
39
40 import org.apache.commons.lang3.AbstractLangTest;
41 import org.junit.jupiter.api.Test;
42 import org.junit.jupiter.params.ParameterizedTest;
43 import org.junit.jupiter.params.provider.MethodSource;
44
45
46
47
48 class PairTest extends AbstractLangTest {
49
50
51 public static Stream<Class<? extends Map>> mapClassFactory() {
52 return Stream.of(ConcurrentHashMap.class, ConcurrentSkipListMap.class, HashMap.class, TreeMap.class, WeakHashMap.class, LinkedHashMap.class);
53 }
54
55 @Test
56 void testAccept() {
57 final Pair<String, String> pair1 = Pair.of("A", "D");
58 final Pair<String, String> pair2 = Pair.of("B", "C");
59 final Map<String, String> map = new HashMap<>();
60 pair1.accept(map::put);
61 pair2.accept(map::put);
62 assertEquals("D", map.get("A"));
63 assertEquals("C", map.get("B"));
64 pair1.accept(map::put);
65 pair2.accept(map::put);
66 assertEquals("D", map.get("A"));
67 assertEquals("C", map.get("B"));
68 }
69
70 @Test
71 void testApply() {
72 final Pair<String, String> pair1 = Pair.of("A", "D");
73 final Pair<String, String> pair2 = Pair.of("B", "C");
74 final Map<String, String> map = new HashMap<>();
75 assertNull(pair1.apply(map::put));
76 assertNull(pair2.apply(map::put));
77 assertEquals("D", map.get("A"));
78 assertEquals("C", map.get("B"));
79 assertEquals("D", pair1.apply(map::put));
80 assertEquals("C", pair2.apply(map::put));
81 assertEquals("D", map.get("A"));
82 assertEquals("C", map.get("B"));
83 }
84
85 @Test
86 void testComparableAllDifferent() {
87 final Pair<String, String> pair1 = Pair.of("A", "D");
88 final Pair<String, String> pair2 = Pair.of("B", "C");
89 assertEquals(0, pair1.compareTo(pair1));
90 assertTrue(pair1.compareTo(pair2) < 0);
91 assertEquals(0, pair2.compareTo(pair2));
92 assertTrue(pair2.compareTo(pair1) > 0);
93 }
94
95 @Test
96 void testComparableLeftEquals() {
97 final Pair<String, String> pair1 = Pair.of("E", "C");
98 final Pair<String, String> pair2 = Pair.of("E", "D");
99 assertEquals(0, pair1.compareTo(pair1));
100 assertTrue(pair1.compareTo(pair2) < 0);
101 assertEquals(0, pair2.compareTo(pair2));
102 assertTrue(pair2.compareTo(pair1) > 0);
103 }
104
105 @Test
106 void testComparableRightEquals() {
107 final Pair<String, String> pair1 = Pair.of("A", "E");
108 final Pair<String, String> pair2 = Pair.of("B", "E");
109 assertEquals(0, pair1.compareTo(pair1));
110 assertTrue(pair1.compareTo(pair2) < 0);
111 assertEquals(0, pair2.compareTo(pair2));
112 assertTrue(pair2.compareTo(pair1) > 0);
113 }
114
115 @Test
116 void testCompatibilityBetweenPairs() {
117 final Pair<Integer, String> pair = ImmutablePair.of(0, "foo");
118 final Pair<Integer, String> pair2 = MutablePair.of(0, "foo");
119 assertEquals(pair, pair2);
120 assertEquals(pair.hashCode(), pair2.hashCode());
121 final HashSet<Pair<Integer, String>> set = new HashSet<>();
122 set.add(pair);
123 assertTrue(set.contains(pair2));
124
125 pair2.setValue("bar");
126 assertNotEquals(pair, pair2);
127 assertNotEquals(pair.hashCode(), pair2.hashCode());
128 }
129
130 @Test
131 void testEmptyArrayGenerics() {
132 final Pair<Integer, String>[] empty = Pair.emptyArray();
133 assertEquals(0, empty.length);
134 }
135
136 @Test
137 void testEmptyArrayLength() {
138 @SuppressWarnings("unchecked")
139 final Pair<Integer, String>[] empty = (Pair<Integer, String>[]) Pair.EMPTY_ARRAY;
140 assertEquals(0, empty.length);
141 }
142
143 @Test
144 void testEqualsAnonynous() {
145 final Pair<String, String> pair = Pair.of("a", "b");
146 final String key = "a";
147 final String value = "b";
148 final Map.Entry<String, String> entry = new Map.Entry<String, String>() {
149
150 @Override
151 public boolean equals(final Object o) {
152 if (!(o instanceof Map.Entry)) {
153 return false;
154 }
155 final Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
156
157 return Objects.equals(getKey(), e.getKey()) && Objects.equals(getValue(), e.getValue());
158 }
159
160 @Override
161 public String getKey() {
162 return key;
163 }
164
165 @Override
166 public String getValue() {
167 return value;
168 }
169
170 @Override
171 public int hashCode() {
172 return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode());
173 }
174
175 @Override
176 public String setValue(final String value) {
177 return null;
178 }
179 };
180 final Map.Entry<String, String> entry2 = new Map.Entry<String, String>() {
181
182 @Override
183 public boolean equals(final Object o) {
184 if (!(o instanceof Map.Entry)) {
185 return false;
186 }
187 final Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
188
189 return Objects.equals(getKey(), e.getKey()) && Objects.equals(getValue(), e.getValue());
190 }
191
192 @Override
193 public String getKey() {
194 return key;
195 }
196
197 @Override
198 public String getValue() {
199 return value;
200 }
201 @Override
202 public int hashCode() {
203 return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode());
204 }
205
206 @Override
207 public String setValue(final String value) {
208 return null;
209 }
210 };
211 assertEquals(pair, entry);
212 assertEquals(pair.hashCode(), entry.hashCode());
213 assertEquals(pair, entry2);
214 assertEquals(pair.hashCode(), entry2.hashCode());
215 assertEquals(entry, entry);
216 assertEquals(entry.hashCode(), entry.hashCode());
217 assertEquals(entry2, entry2);
218 assertEquals(entry2.hashCode(), entry2.hashCode());
219 assertEquals(entry, entry2);
220 assertEquals(entry.hashCode(), entry2.hashCode());
221 assertEquals(entry, pair);
222 assertEquals(entry.hashCode(), pair.hashCode());
223
224 }
225
226 @Test
227 void testFormattable_padded() {
228 final Pair<String, String> pair = Pair.of("Key", "Value");
229 assertEquals(" (Key,Value)", String.format("%1$20s", pair));
230 }
231
232 @Test
233 void testFormattable_simple() {
234 final Pair<String, String> pair = Pair.of("Key", "Value");
235 assertEquals("(Key,Value)", String.format("%1$s", pair));
236 }
237
238 @ParameterizedTest()
239 @MethodSource("org.apache.commons.lang3.tuple.PairTest#mapClassFactory")
240 public <K, V> void testMapEntries(final Class<Map<Integer, String>> clazz) throws InstantiationException, IllegalAccessException {
241 testMapEntry(clazz.newInstance());
242 }
243
244 public <K, V> void testMapEntries(final Map<Integer, String> map) {
245 testMapEntry(map);
246 }
247
248 private void testMapEntry(final Map<Integer, String> map) {
249 map.put(0, "foo");
250 final Entry<Integer, String> entry = map.entrySet().iterator().next();
251 final Pair<Integer, String> pair = ImmutablePair.of(0, "foo");
252 assertEquals(pair, entry);
253 assertEquals(pair.hashCode(), entry.hashCode());
254
255 map.clear();
256 map.put(0, "value1");
257 map.put(1, "value2");
258 map.entrySet().forEach(e -> {
259 final Pair<Integer, String> p = ImmutablePair.of(e.getKey(), e.getValue());
260 assertEquals(p, e);
261 assertEquals(p.hashCode(), e.hashCode());
262 });
263 }
264
265 @Test
266 void testOfNonNull() {
267 assertNullPointerException(() -> Pair.ofNonNull(null, null));
268 assertNullPointerException(() -> Pair.ofNonNull(null, "x"));
269 assertNullPointerException(() -> Pair.ofNonNull("x", null));
270 final Pair<String, String> pair = Pair.ofNonNull("x", "y");
271 assertEquals("x", pair.getLeft());
272 assertEquals("y", pair.getRight());
273 }
274
275 @Test
276 void testPairOfAbstractMapSimpleEntry() {
277 final Entry<Integer, String> entry = new AbstractMap.SimpleEntry<>(0, "foo");
278 final Pair<Integer, String> pair = Pair.of(entry);
279 assertEquals(entry.getKey(), pair.getLeft());
280 assertEquals(entry.getValue(), pair.getRight());
281 assertEquals(entry, pair);
282 assertEquals(entry.hashCode(), pair.hashCode());
283 assertEquals(pair, entry);
284 assertEquals(pair.hashCode(), entry.hashCode());
285 }
286
287 @Test
288 void testPairOfMapEntry() {
289 final HashMap<Integer, String> map = new HashMap<>();
290 map.put(0, "foo");
291 final Entry<Integer, String> entry = map.entrySet().iterator().next();
292 final Pair<Integer, String> pair = Pair.of(entry);
293 assertEquals(entry.getKey(), pair.getLeft());
294 assertEquals(entry.getValue(), pair.getRight());
295 }
296
297 @Test
298 void testPairOfObjects() {
299 final Pair<Integer, String> pair = Pair.of(0, "foo");
300 assertInstanceOf(ImmutablePair.class, pair);
301 assertEquals(0, ((ImmutablePair<Integer, String>) pair).left.intValue());
302 assertEquals("foo", ((ImmutablePair<Integer, String>) pair).right);
303 final Pair<Object, String> pair2 = Pair.of(null, "bar");
304 assertInstanceOf(ImmutablePair.class, pair2);
305 assertNull(((ImmutablePair<Object, String>) pair2).left);
306 assertEquals("bar", ((ImmutablePair<Object, String>) pair2).right);
307 final Pair<?, ?> pair3 = Pair.of(null, null);
308 assertNull(pair3.getLeft());
309 assertNull(pair3.getRight());
310 }
311
312 @Test
313 void testToString() {
314 final Pair<String, String> pair = Pair.of("Key", "Value");
315 assertEquals("(Key,Value)", pair.toString());
316 }
317
318 @Test
319 void testToStringCustom() {
320 final Calendar date = Calendar.getInstance();
321 date.set(2011, Calendar.APRIL, 25);
322 final Pair<String, Calendar> pair = Pair.of("DOB", date);
323 assertEquals("Test created on 04-25-2011", pair.toString("Test created on %2$tm-%2$td-%2$tY"));
324 }
325
326 }