1   package com.atlassian.sal.core.pluginsettings;
2   
3   import java.util.ArrayList;
4   import java.util.Arrays;
5   import java.util.HashMap;
6   import java.util.List;
7   import java.util.Map;
8   import java.util.Properties;
9   
10  import org.apache.commons.lang.StringUtils;
11  import org.junit.Before;
12  import org.junit.Test;
13  
14  import static org.junit.Assert.assertEquals;
15  import static org.junit.Assert.assertNull;
16  import static org.junit.Assert.assertTrue;
17  
18  public class TestAbstractStringPluginSettings
19  {
20      private PluginSettingsAcceptor acceptor;
21      private static final String KEY = "some key";
22  
23      @Before
24      public void setUp()
25      {
26          acceptor = new PluginSettingsAcceptor();
27      }
28  
29      @Test
30      public void testString()
31      {
32          String value = "this is the value";
33          
34          acceptor.put(KEY, value);
35          assertEquals("Values should be equal.", value, acceptor.get(KEY));
36      }
37  
38      @Test(expected = IllegalArgumentException.class)
39      public void testGetWithNullKey()
40      {
41          acceptor.get(null);
42      }
43  
44      @Test
45      public void getWithLongKeyDoesNotCauseError()
46      {
47          assertNull(acceptor.get(StringUtils.repeat("a", 101)));
48      }
49  
50      @Test
51      public void getWithVeryLongKeyDoesNotCauseError()
52      {
53          assertNull(acceptor.get(StringUtils.repeat("a", 256)));
54      }
55      
56      @Test(expected = IllegalArgumentException.class)
57      public void testPutWithNullKey()
58      {
59          acceptor.put(null, "foo");
60      }
61  
62      @Test
63      public void putWith100CharacterKeyIsAlwaysAccepted()
64      {
65          acceptor.put(StringUtils.repeat("a", 100), "foo");
66      }
67      
68      /**
69       * The SAL layer accepts this key. The underlying storage layer
70       * may fail in a real application.
71       */
72      @Test
73      public void putWithVeryLongKeyIsAcceptedBySalLayer()
74      {
75          String previousValue = System.setProperty("atlassian.dev.mode", "false");
76          try
77          {
78              // A new instance to pick up the system property
79              acceptor = new PluginSettingsAcceptor();
80              acceptor.put(StringUtils.repeat("a", 255), "foo");
81          }
82          finally
83          {
84              System.setProperty("atlassian.dev.mode", StringUtils.defaultString(previousValue));
85          }
86      }
87      
88      @Test(expected = IllegalArgumentException.class)
89      public void putWithOverlyLongKeyFails()
90      {
91          acceptor.put(StringUtils.repeat("a", 256), "foo");
92      }
93  
94      @Test(expected = IllegalArgumentException.class)
95      public void putWithLongKeyFailsInDevMode()
96      {
97          String previousValue = System.setProperty("atlassian.dev.mode", "true");
98          try
99          {
100             // A new instance to pick up the system property
101             acceptor = new PluginSettingsAcceptor();
102             acceptor.put(StringUtils.repeat("a", 101), "foo");
103         }
104         finally
105         {
106             System.setProperty("atlassian.dev.mode", StringUtils.defaultString(previousValue));
107         }
108     }
109     
110     @Test
111     public void testSpecialCharsString()
112     {
113         String value = "this\tis\bthe\nvalue\rand\ffun";
114 
115         acceptor.put(KEY, value);
116         assertEquals("Values should be equal.", value, acceptor.get(KEY));
117     }
118 
119     @Test
120     public void testList()
121     {
122         final List<String> value = new ArrayList<String>();
123         final String first = "Beanz Meanz Heinz";
124         final String second = "Sic 'em Rex!";
125         
126         value.add(first);
127         value.add(second);
128         
129         acceptor.put(KEY, value);
130         
131         final Object actual = acceptor.get(KEY);
132         
133         assertTrue(actual instanceof List);
134         
135         final List<?> real = (List<?>) actual;
136         
137         assertEquals("List size should be the same", 2, real.size());
138         assertEquals("List should still be in order", first, real.get(0));
139         assertEquals("List should still be in order", second, real.get(1));
140     }
141 
142     @Test
143     public void testSpecialCharsInList()
144     {
145         final List<String> value = new ArrayList<String>();
146 
147         final String first = "At\tfirst\bwhen\nI\rsee\fyou cry";
148         final String second = "\tit\bmakes\nme\rsmile\f";
149 
150         value.add(first);
151         value.add(second);
152         acceptor.put(KEY, value);
153 
154         final Object actual = acceptor.get(KEY);
155 
156         assertTrue(actual instanceof List);
157 
158         final List<?> real = (List<?>) actual;
159 
160         assertEquals("List size should be the same", 2, real.size());
161         assertEquals("The content should match the original data", first, real.get(0));
162         assertEquals("The content should match the original data", second, real.get(1));
163     }
164 
165     @Test
166     public void testMap()
167     {
168         final Map<String, String> value = new HashMap<String, String>();
169         final String[] first = {"antzpantz", "Sic 'em Rex!"}; 
170         final String[] second = {"homestar", "Lookin' at a thing in a bag"}; 
171         final String[] third = {"he-man", "By the power of Greyskull!!!"};
172         
173         mapPut(value, first);
174         mapPut(value, second);
175         mapPut(value, third);
176         
177         acceptor.put(KEY, value);
178 
179         final Object actual = acceptor.get(KEY);
180         
181         assertTrue(actual instanceof Map);
182         
183         final Map<?, ?> real = (Map<?, ?>) actual;
184         
185         assertEquals("The size should be the same as what was entered.", 3, real.entrySet().size());
186         assertMapEntryEquals("Map should retrieve the correct value for each key", real, first);
187         assertMapEntryEquals("Map should retrieve the correct value for each key", real, second);
188         assertMapEntryEquals("Map should retrieve the correct value for each key", real, third);
189     }
190 
191     @Test
192     public void testSpecialCharsInMap()
193     {
194         final Map<String, String> value = new HashMap<String, String>();
195         final String[] first = {"one", "one\tthing\bI\ndon't\rknow\fwhy"};
196         final String[] second = {"two", "I\tdoesn't\beven\nmatter\rhow\fhard you try"};
197 
198         mapPut(value, first);
199         mapPut(value, second);
200 
201         acceptor.put(KEY, value);
202 
203         final Object actual = acceptor.get(KEY);
204 
205         assertTrue(actual instanceof Map);
206 
207         final Map<?, ?> real = (Map<?, ?>) actual;
208 
209         assertEquals("The size should be the same as what was entered.", 2, real.entrySet().size());
210         assertMapEntryEquals("The content should match the original data", real, first);
211         assertMapEntryEquals("The content should match the original data", real, second);
212     }
213 
214     @Test
215     public void testEmptyMap()
216     {
217         final Map<String, String> value = new HashMap<String, String>();
218         acceptor.put(KEY, value);
219         final Object actual = acceptor.get(KEY);
220         assertTrue(actual instanceof Map);
221         assertTrue(((Map<?, ?>) actual).isEmpty());
222     }
223 
224     @Test
225     public void testProperties()
226     {
227         final Properties value = new Properties();
228         final String[] first = {"antzpantz", "Sic 'em Rex!"}; 
229         final String[] second = {"homestar", "Lookin' at a thing in a bag"}; 
230         final String[] third = {"he-man", "By the power of Greyskull!!!"};
231      
232         propertiesPut(value, first);        
233         propertiesPut(value, second);        
234         propertiesPut(value, third);
235         
236         acceptor.put(KEY, value);
237         
238         final Object actual = acceptor.get(KEY);
239         
240         assertTrue(actual instanceof Properties);
241         
242         final Properties real = (Properties) actual;
243         
244         assertPropertiesEntryEquals("Propertis should contain the same value for each key", real, first);
245         assertPropertiesEntryEquals("Propertis should contain the same value for each key", real, second);
246         assertPropertiesEntryEquals("Propertis should contain the same value for each key", real, third);
247     }
248 
249     @Test
250     public void testSpecialCharsInKeys()
251     {
252         String key1 = "this\tis\bthe\nkey\rsample\fhohoho1";
253         String value1 = "value1";
254 
255         String key2 = "this\tis\bthe\nkey\rsample\fhohoho2";
256         List<String> value2 = Arrays.asList("value2");
257 
258         String key3 = "this\tis\bthe\nkey\rsample\fhohoho3";
259         Map<String, String> value3 = new HashMap<String, String>();
260         value3.put(key3 + "inner1", "value3inner1");
261         value3.put(key3 + "inner2", "value3inner2");
262 
263         String key4 = "this\tis\bthe\nkey\rsample\fhohoho4";
264         Properties value4 = new Properties();
265         value4.setProperty(key4 + "inner1", "value4inner1");
266         value4.setProperty(key4 + "inner2", "value4inner2");
267 
268         acceptor.put(key1, value1);
269         acceptor.put(key2, value2);
270         acceptor.put(key3, value3);
271         acceptor.put(key4, value4);
272 
273         assertEquals("Values should be equal.", value1, acceptor.get(key1));
274         assertEquals("Values should be equal.", value2, acceptor.get(key2));
275         assertEquals("Values should be equal.", value3, acceptor.get(key3));
276         assertEquals("Values should be equal.", value4, acceptor.get(key4));
277     }
278 
279     @Test
280     public void testPutReturnValueNull()
281     {
282         List<String> value = Arrays.asList("one", "two", "three");
283         assertNull(acceptor.put(KEY, value));
284     }
285 
286     @Test
287     public void testPutReturnValueOldValue()
288     {
289         List<String> oldValue = Arrays.asList("two", "three", "four");
290         acceptor.put(KEY, oldValue);
291         List<String> value = Arrays.asList("one", "two", "three");
292         assertEquals(oldValue, acceptor.put(KEY, value));
293     }
294 
295     @Test
296     public void testRemoveReturnValueNull()
297     {
298         assertNull(acceptor.remove(KEY));
299     }
300 
301     @Test
302     public void testRemoveReturnValueOldValue()
303     {
304         List<String> oldValue = Arrays.asList("two", "three", "four");
305         acceptor.put(KEY, oldValue);
306         assertEquals(oldValue, acceptor.remove(KEY));
307     }
308 
309     @Test(expected = IllegalArgumentException.class)
310     public void testRemoveWithNullKey()
311     {
312         acceptor.remove(null);
313     }
314 
315     @Test
316     public void removeWithLongKeyDoesNotFail()
317     {
318         assertNull(acceptor.remove(StringUtils.repeat("a", 101)));
319     }
320 
321     @Test
322     public void removeWithVeryLongKeyDoesNotFail()
323     {
324         assertNull(acceptor.remove(StringUtils.repeat("a", 256)));
325     }
326     
327     private void assertPropertiesEntryEquals(String errMsg, Properties real, String[] kvPair)
328     {
329         assertEquals(errMsg, kvPair[1], real.getProperty(kvPair[0]));
330     }
331 
332     private static void propertiesPut(Properties properties, String[] values)
333     {
334         properties.setProperty(values[0], values[1]);
335     }
336 
337     private static void assertMapEntryEquals(String errMsg, Map<?, ?> real, String[] kvPair)
338     {
339         assertEquals(errMsg, kvPair[1], real.get(kvPair[0]));
340     }
341 
342     private static void mapPut(Map<String, String> map, String[] values)
343     {
344         map.put(values[0], values[1]);
345     }
346 
347 
348     private static final class PluginSettingsAcceptor extends AbstractStringPluginSettings
349     {
350         private final Map<String,String> backingStore = new HashMap<String, String>();
351         
352         protected void putActual(String key, String val)
353         {
354             backingStore.put(key, val);
355         }
356 
357         protected String getActual(String key)
358         {
359             return backingStore.get(key);                        
360         }
361 
362         protected void removeActual(String key)
363         {
364             backingStore.remove(key);
365         }
366     }
367 }