View Javadoc
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  package org.apache.commons.collections4.map;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertNotNull;
22  import static org.junit.jupiter.api.Assertions.assertNull;
23  import static org.junit.jupiter.api.Assertions.assertThrows;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  
26  import java.util.HashMap;
27  import java.util.Map;
28  import java.util.concurrent.TimeUnit;
29  
30  import org.apache.commons.collections4.collection.AbstractCollectionTest;
31  import org.apache.commons.collections4.map.PassiveExpiringMap.ExpirationPolicy;
32  import org.junit.jupiter.api.Test;
33  
34  /**
35   * JUnit tests.
36   *
37   * @param <K> the key type.
38   * @param <V> the value type.
39   */
40  public class PassiveExpiringMapTest<K, V> extends AbstractMapTest<PassiveExpiringMap<K, V>, K, V> {
41  
42      private static final class TestExpirationPolicy
43          implements ExpirationPolicy<Integer, String> {
44  
45          private static final long serialVersionUID = 1L;
46  
47          @Override
48          public long expirationTime(final Integer key, final String value) {
49              // odd keys expire immediately, even keys never expire
50              if (key == null) {
51                  return 0;
52              }
53  
54              if (key.intValue() % 2 == 0) {
55                  return -1;
56              }
57  
58              return 0;
59          }
60      }
61  
62  //    public void testCreate() throws Exception {
63  //        writeExternalFormToDisk((java.io.Serializable) makeObject(),
64  //                "src/test/resources/data/test/PassiveExpiringMap.emptyCollection.version4.obj");
65  //
66  //        writeExternalFormToDisk((java.io.Serializable) makeFullMap(),
67  //                "src/test/resources/data/test/PassiveExpiringMap.fullCollection.version4.obj");
68  //    }
69  
70      @Override
71      public String getCompatibilityVersion() {
72          return "4";
73      }
74  
75      @Override
76      protected int getIterationBehaviour() {
77          return AbstractCollectionTest.UNORDERED;
78      }
79  
80      private Map<Integer, String> makeDecoratedTestMap() {
81          final Map<Integer, String> m = new HashMap<>();
82          m.put(Integer.valueOf(1), "one");
83          m.put(Integer.valueOf(2), "two");
84          m.put(Integer.valueOf(3), "three");
85          m.put(Integer.valueOf(4), "four");
86          m.put(Integer.valueOf(5), "five");
87          m.put(Integer.valueOf(6), "six");
88          return new PassiveExpiringMap<>(new TestExpirationPolicy(), m);
89      }
90  
91      @Override
92      public PassiveExpiringMap<K, V> makeObject() {
93          return new PassiveExpiringMap<>();
94      }
95  
96      private Map<Integer, String> makeTestMap() {
97          final Map<Integer, String> m =
98                  new PassiveExpiringMap<>(new TestExpirationPolicy());
99          m.put(Integer.valueOf(1), "one");
100         m.put(Integer.valueOf(2), "two");
101         m.put(Integer.valueOf(3), "three");
102         m.put(Integer.valueOf(4), "four");
103         m.put(Integer.valueOf(5), "five");
104         m.put(Integer.valueOf(6), "six");
105         return m;
106     }
107 
108     @Test
109     public void testConstructors() {
110         assertThrows(NullPointerException.class, () -> {
111             final Map<String, String> map = null;
112             new PassiveExpiringMap<>(map);
113         });
114         assertThrows(NullPointerException.class, () -> {
115             final ExpirationPolicy<String, String> policy = null;
116             new PassiveExpiringMap<>(policy);
117         });
118         assertThrows(NullPointerException.class, () -> {
119             final TimeUnit unit = null;
120             new PassiveExpiringMap<String, String>(10L, unit);
121         });
122     }
123 
124     @Test
125     public void testContainsKey() {
126         final Map<Integer, String> m = makeTestMap();
127         assertFalse(m.containsKey(Integer.valueOf(1)));
128         assertFalse(m.containsKey(Integer.valueOf(3)));
129         assertFalse(m.containsKey(Integer.valueOf(5)));
130         assertTrue(m.containsKey(Integer.valueOf(2)));
131         assertTrue(m.containsKey(Integer.valueOf(4)));
132         assertTrue(m.containsKey(Integer.valueOf(6)));
133     }
134 
135     @Test
136     public void testContainsValue() {
137         final Map<Integer, String> m = makeTestMap();
138         assertFalse(m.containsValue("one"));
139         assertFalse(m.containsValue("three"));
140         assertFalse(m.containsValue("five"));
141         assertTrue(m.containsValue("two"));
142         assertTrue(m.containsValue("four"));
143         assertTrue(m.containsValue("six"));
144     }
145 
146     @Test
147     public void testDecoratedMap() {
148         // entries shouldn't expire
149         final Map<Integer, String> m = makeDecoratedTestMap();
150         assertEquals(6, m.size());
151         assertEquals("one", m.get(Integer.valueOf(1)));
152 
153         // removing a single item shouldn't affect any other items
154         assertEquals("two", m.get(Integer.valueOf(2)));
155         m.remove(Integer.valueOf(2));
156         assertEquals(5, m.size());
157         assertEquals("one", m.get(Integer.valueOf(1)));
158         assertNull(m.get(Integer.valueOf(2)));
159 
160         // adding a single, even item shouldn't affect any other items
161         assertNull(m.get(Integer.valueOf(2)));
162         m.put(Integer.valueOf(2), "two");
163         assertEquals(6, m.size());
164         assertEquals("one", m.get(Integer.valueOf(1)));
165         assertEquals("two", m.get(Integer.valueOf(2)));
166 
167         // adding a single, odd item (one that expires) shouldn't affect any
168         // other items
169         // put the entry expires immediately
170         m.put(Integer.valueOf(1), "one-one");
171         assertEquals(5, m.size());
172         assertNull(m.get(Integer.valueOf(1)));
173         assertEquals("two", m.get(Integer.valueOf(2)));
174     }
175 
176     @Test
177     public void testEntrySet() {
178         final Map<Integer, String> m = makeTestMap();
179         assertEquals(3, m.entrySet().size());
180     }
181 
182     @Test
183     public void testExpiration() throws InterruptedException {
184         validateExpiration(new PassiveExpiringMap<>(500), 500);
185         validateExpiration(new PassiveExpiringMap<>(1000), 1000);
186         validateExpiration(new PassiveExpiringMap<>(new PassiveExpiringMap.ConstantTimeToLiveExpirationPolicy<>(500)), 500);
187         validateExpiration(new PassiveExpiringMap<>(new PassiveExpiringMap.ConstantTimeToLiveExpirationPolicy<>(1, TimeUnit.SECONDS)), 1000);
188     }
189 
190     @Test
191     public void testGet() {
192         final Map<Integer, String> m = makeTestMap();
193         assertNull(m.get(Integer.valueOf(1)));
194         assertEquals("two", m.get(Integer.valueOf(2)));
195         assertNull(m.get(Integer.valueOf(3)));
196         assertEquals("four", m.get(Integer.valueOf(4)));
197         assertNull(m.get(Integer.valueOf(5)));
198         assertEquals("six", m.get(Integer.valueOf(6)));
199     }
200 
201     @Test
202     public void testIsEmpty() {
203         Map<Integer, String> m = makeTestMap();
204         assertFalse(m.isEmpty());
205 
206         // remove just evens
207         m = makeTestMap();
208         m.remove(Integer.valueOf(2));
209         m.remove(Integer.valueOf(4));
210         m.remove(Integer.valueOf(6));
211         assertTrue(m.isEmpty());
212     }
213 
214     @Test
215     public void testKeySet() {
216         final Map<Integer, String> m = makeTestMap();
217         assertEquals(3, m.size());
218     }
219 
220     @Test
221     public void testPut() {
222         final Map<Integer, String> m = makeTestMap();
223         assertNull(m.put(Integer.valueOf(1), "ONE"));
224         assertEquals("two", m.put(Integer.valueOf(2), "TWO"));
225         assertNull(m.put(Integer.valueOf(3), "THREE"));
226         assertEquals("four", m.put(Integer.valueOf(4), "FOUR"));
227         assertNull(m.put(Integer.valueOf(5), "FIVE"));
228         assertEquals("six", m.put(Integer.valueOf(6), "SIX"));
229     }
230 
231     @Test
232     public void testSize() {
233         final Map<Integer, String> m = makeTestMap();
234         assertEquals(3, m.size());
235     }
236 
237     @Test
238     public void testValues() {
239         final Map<Integer, String> m = makeTestMap();
240         assertEquals(3, m.size());
241     }
242 
243     @Test
244     public void testZeroTimeToLive() {
245         // item should not be available
246         final PassiveExpiringMap<String, String> m = new PassiveExpiringMap<>(0L);
247         m.put("a", "b");
248         assertNull(m.get("a"));
249     }
250 
251     private void validateExpiration(final Map<String, String> map, final long timeout) throws InterruptedException {
252         map.put("a", "b");
253         assertNotNull(map.get("a"));
254         Thread.sleep(2 * timeout);
255         assertNull(map.get("a"));
256     }
257 
258 }