JAL-4059 updated test for StringUtils
[jalview.git] / test / jalview / util / StringUtilsTest.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.util;
22
23 import static org.testng.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertNull;
25 import static org.testng.AssertJUnit.assertTrue;
26
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.List;
30
31 import org.testng.annotations.BeforeClass;
32 import org.testng.annotations.Test;
33
34 import jalview.gui.JvOptionPane;
35
36 public class StringUtilsTest
37 {
38
39   @BeforeClass(alwaysRun = true)
40   public void setUpJvOptionPane()
41   {
42     JvOptionPane.setInteractiveMode(false);
43     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
44   }
45
46   @Test(groups = { "Functional" })
47   public void testInsertCharAt()
48   {
49     char[] c1 = "ABC".toCharArray();
50     char[] expected = new char[] { 'A', 'B', 'C', 'w', 'w' };
51     assertTrue(Arrays.equals(expected,
52             StringUtils.insertCharAt(c1, 3, 2, 'w')));
53     expected = new char[] { 'A', 'B', 'C', 'w', 'w' };
54     assertTrue(Arrays.equals(expected,
55             StringUtils.insertCharAt(c1, 4, 2, 'w')));
56     assertTrue(Arrays.equals(expected,
57             StringUtils.insertCharAt(c1, 5, 2, 'w')));
58     assertTrue(Arrays.equals(expected,
59             StringUtils.insertCharAt(c1, 6, 2, 'w')));
60     assertTrue(Arrays.equals(expected,
61             StringUtils.insertCharAt(c1, 7, 2, 'w')));
62   }
63
64   @Test(groups = { "Functional" })
65   public void testDeleteChars()
66   {
67     char[] c1 = "ABC".toCharArray();
68
69     // delete second position
70     assertTrue(
71             Arrays.equals(new char[]
72             { 'A', 'C' }, StringUtils.deleteChars(c1, 1, 2)));
73
74     // delete positions 1 and 2
75     assertTrue(
76             Arrays.equals(new char[]
77             { 'C' }, StringUtils.deleteChars(c1, 0, 2)));
78
79     // delete positions 1-3
80     assertTrue(Arrays.equals(new char[] {},
81             StringUtils.deleteChars(c1, 0, 3)));
82
83     // delete position 3
84     assertTrue(
85             Arrays.equals(new char[]
86             { 'A', 'B' }, StringUtils.deleteChars(c1, 2, 3)));
87
88     // out of range deletion is ignore
89     assertTrue(Arrays.equals(c1, StringUtils.deleteChars(c1, 3, 4)));
90   }
91
92   @Test(groups = { "Functional" })
93   public void testGetLastToken()
94   {
95     assertNull(StringUtils.getLastToken(null, null));
96     assertNull(StringUtils.getLastToken(null, "/"));
97     assertEquals("a", StringUtils.getLastToken("a", null));
98
99     assertEquals("abc", StringUtils.getLastToken("abc", "/"));
100     assertEquals("c", StringUtils.getLastToken("abc", "b"));
101     assertEquals("file1.dat", StringUtils.getLastToken(
102             "file://localhost:8080/data/examples/file1.dat", "/"));
103   }
104
105   @Test(groups = { "Functional" })
106   public void testSeparatorListToArray()
107   {
108     String[] result = StringUtils.separatorListToArray(
109             "foo=',',min='foo',max='1,2,3',fa=','", ",");
110     assertEquals("[foo=',', min='foo', max='1,2,3', fa=',']",
111             Arrays.toString(result));
112     /*
113      * Comma nested in '' is not treated as delimiter; tokens are not trimmed
114      */
115     result = StringUtils.separatorListToArray("minsize='2', sep=','", ",");
116     assertEquals("[minsize='2',  sep=',']", Arrays.toString(result));
117
118     /*
119      * String delimited by | containing a quoted | (should not be treated as
120      * delimiter)
121      */
122     assertEquals("[abc='|'d, ef, g]", Arrays.toString(
123             StringUtils.separatorListToArray("abc='|'d|ef|g", "|")));
124
125     /*
126      * edge cases
127      */
128     assertEquals("[abc=';'d, ef, g, key='val;ue;key2=what]",
129             Arrays.toString(StringUtils.separatorListToArray(
130                     "abc=';'d;ef;g;key='val;ue;key2=what", ";")));
131     assertEquals("[hello\\world, jello'\\world', mello'wo\\'rld']",
132             Arrays.toString(StringUtils.separatorListToArray(
133                     "hello\\world;jello'\\world';mello'wo\\'rld'", ";")));
134     // this next one checks that an escaped single quote doesn't end a quoted
135     // section so the following separator is treated as part of the quoted text,
136     // not as a separator.
137     assertEquals("[hello\\world, jello'\\world', mello'wo\\'r;ld']",
138             Arrays.toString(StringUtils.separatorListToArray(
139                     "hello\\world;jello'\\world';mello'wo\\'r;ld'", ";")));
140     assertEquals("[hello\\;jello, mello\\;';'w, world]",
141             Arrays.toString(StringUtils.separatorListToArray(
142                     "hello\\;jello;mello\\;';'w;world", ";")));
143   }
144
145   @Test(groups = { "Functional" })
146   public void testArrayToSeparatorList()
147   {
148     assertEquals("*", StringUtils.arrayToSeparatorList(null, "*"));
149     assertEquals("*",
150             StringUtils.arrayToSeparatorList(new String[] {}, "*"));
151     assertEquals("a*bc*cde",
152             StringUtils.arrayToSeparatorList(new String[]
153             { "a", "bc", "cde" }, "*"));
154     assertEquals("a*cde",
155             StringUtils.arrayToSeparatorList(new String[]
156             { "a", null, "cde" }, "*"));
157     assertEquals("a**cde",
158             StringUtils.arrayToSeparatorList(new String[]
159             { "a", "", "cde" }, "*"));
160     // delimiter within token is not (yet) escaped
161     assertEquals("a*b*c*cde",
162             StringUtils.arrayToSeparatorList(new String[]
163             { "a", "b*c", "cde" }, "*"));
164   }
165
166   @Test(groups = { "Functional" })
167   public void testListToDelimitedString()
168   {
169     assertEquals("", StringUtils.listToDelimitedString(null, ";"));
170     List<String> list = new ArrayList<>();
171     assertEquals("", StringUtils.listToDelimitedString(list, ";"));
172     list.add("now");
173     assertEquals("now", StringUtils.listToDelimitedString(list, ";"));
174     list.add("is");
175     assertEquals("now;is", StringUtils.listToDelimitedString(list, ";"));
176     assertEquals("now ; is",
177             StringUtils.listToDelimitedString(list, " ; "));
178     list.add("the");
179     list.add("winter");
180     list.add("of");
181     list.add("our");
182     list.add("discontent");
183     assertEquals("now is the winter of our discontent",
184             StringUtils.listToDelimitedString(list, " "));
185   }
186
187   @Test(groups = { "Functional" })
188   public void testParseInt()
189   {
190     assertEquals(0, StringUtils.parseInt(null));
191     assertEquals(0, StringUtils.parseInt(""));
192     assertEquals(0, StringUtils.parseInt("x"));
193     assertEquals(0, StringUtils.parseInt("1.2"));
194     assertEquals(33, StringUtils.parseInt("33"));
195     assertEquals(33, StringUtils.parseInt("+33"));
196     assertEquals(-123, StringUtils.parseInt("-123"));
197     // too big for an int:
198     assertEquals(0,
199             StringUtils.parseInt(String.valueOf(Integer.MAX_VALUE) + "1"));
200   }
201
202   @Test(groups = { "Functional" })
203   public void testCompareVersions()
204   {
205     assertEquals(0, StringUtils.compareVersions(null, null));
206     assertEquals(0, StringUtils.compareVersions("2.8.3", null));
207
208     /*
209      * same version returns 0
210      */
211     assertEquals(0, StringUtils.compareVersions("2.8", "2.8"));
212     assertEquals(0, StringUtils.compareVersions("2.8.3", "2.8.3"));
213     assertEquals(0, StringUtils.compareVersions("2.8.3b1", "2.8.3b1", "b"));
214     assertEquals(0, StringUtils.compareVersions("2.8.3B1", "2.8.3b1", "b"));
215     assertEquals(0, StringUtils.compareVersions("2.8.3b1", "2.8.3B1", "b"));
216
217     /*
218      * v1 < v2 returns -1
219      */
220     assertEquals(-1, StringUtils.compareVersions("2.8.3", "2.8.4"));
221     assertEquals(-1, StringUtils.compareVersions("2.8.3", "2.9"));
222     assertEquals(-1, StringUtils.compareVersions("2.8.3", "2.9.2"));
223     assertEquals(-1, StringUtils.compareVersions("2.8", "2.8.3"));
224     assertEquals(-1, StringUtils.compareVersions("2.8.3", "2.8.3b1", "b"));
225     assertEquals(-1,
226             StringUtils.compareVersions("2.8.3b1", "2.8.3b2", "b"));
227     assertEquals(-1, StringUtils.compareVersions("2.8", "2.8.0", "b"));
228     assertEquals(-1, StringUtils.compareVersions("2", "12"));
229     assertEquals(-1, StringUtils.compareVersions("3.2.4", "3.12.11"));
230
231     /*
232      * v1 > v2 returns +1
233      */
234     assertEquals(1, StringUtils.compareVersions("2.8.3", "2.8"));
235     assertEquals(1, StringUtils.compareVersions("2.8.0", "2.8"));
236     assertEquals(1, StringUtils.compareVersions("2.8.4", "2.8.3"));
237     assertEquals(1, StringUtils.compareVersions("2.8.3b1", "2.8.3", "b"));
238     assertEquals(1, StringUtils.compareVersions("2.8.3", "2.8.2b1", "b"));
239     assertEquals(1, StringUtils.compareVersions("2.8.0b2", "2.8.0b1", "b"));
240     assertEquals(1, StringUtils.compareVersions("12", "2"));
241     assertEquals(1, StringUtils.compareVersions("3.12.11", "3.2.4"));
242   }
243
244   @Test(groups = { "Functional" })
245   public void testToSentenceCase()
246   {
247     assertEquals("John", StringUtils.toSentenceCase("john"));
248     assertEquals("John", StringUtils.toSentenceCase("JOHN"));
249     assertEquals("John and james",
250             StringUtils.toSentenceCase("JOHN and JAMES"));
251     assertEquals("J", StringUtils.toSentenceCase("j"));
252     assertEquals("", StringUtils.toSentenceCase(""));
253     assertNull(StringUtils.toSentenceCase(null));
254   }
255
256   @Test(groups = { "Functional" })
257   public void testStripHtmlTags()
258   {
259     assertNull(StringUtils.stripHtmlTags(null));
260     assertEquals("", StringUtils.stripHtmlTags(""));
261     assertEquals("<a href=\"something\">label</href>",
262             StringUtils.stripHtmlTags(
263                     "<html><a href=\"something\">label</href></html>"));
264
265     // if no "<html>" tag, < and > get html-encoded (not sure why)
266     assertEquals("&lt;a href=\"something\"&gt;label&lt;/href&gt;",
267             StringUtils
268                     .stripHtmlTags("<a href=\"something\">label</href>"));
269
270     // </body> gets removed but not <body> (is this intentional?)
271     assertEquals("<body><p>hello", StringUtils
272             .stripHtmlTags("<html><body><p>hello</body></html>"));
273
274     assertEquals("kdHydro &lt; 12.53",
275             StringUtils.stripHtmlTags("kdHydro < 12.53"));
276   }
277
278   @Test(groups = { "Functional" })
279   public void testUrlEncode()
280   {
281     // degenerate cases
282     assertNull(StringUtils.urlEncode(null, ";,"));
283     assertEquals("", StringUtils.urlEncode("", ""));
284     assertEquals("", StringUtils.urlEncode("", ";,"));
285
286     // sanity checks, see
287     // https://en.wikipedia.org/wiki/Percent-encoding#Percent-encoding_reserved_characters
288     assertEquals("+", StringUtils.urlEncode(" ", " "));
289     assertEquals("%25", StringUtils.urlEncode("%", "%"));
290     assertEquals(".", StringUtils.urlEncode(".", ".")); // note . is not encoded
291     assertEquals("%3A", StringUtils.urlEncode(":", ":"));
292     assertEquals("%3B", StringUtils.urlEncode(";", ";"));
293     assertEquals("%3D", StringUtils.urlEncode("=", "="));
294     assertEquals("%2C", StringUtils.urlEncode(",", ","));
295
296     // check % does not get recursively encoded!
297     assertEquals("a%25b%3Dc%3Bd%3Ae%2C%2C",
298             StringUtils.urlEncode("a%b=c;d:e,,", "=,;:%"));
299
300     // = not in the list for encoding
301     assertEquals("a=b", StringUtils.urlEncode("a=b", ";,"));
302
303     // encode = (as %3B) and ; (as %3D)
304     assertEquals("a%3Db.c%3B", StringUtils.urlEncode("a=b.c;", ";=,"));
305
306     // . and space not in the list for encoding
307     assertEquals("a%3Db.c d", StringUtils.urlEncode("a=b.c d", ";=,"));
308
309     // encode space also (as +)
310     assertEquals("a%3Db.c+d", StringUtils.urlEncode("a=b.c d", ";=, "));
311
312     // . does not get encoded even if requested - behaviour of URLEncoder
313     assertEquals("a%3Db.c+d.e%3Df",
314             StringUtils.urlEncode("a=b.c d.e=f", ";=,. "));
315   }
316
317   @Test(groups = { "Functional" })
318   public void testUrlDecode()
319   {
320     // degenerate cases
321     assertNull(StringUtils.urlDecode(null, ";,"));
322     assertEquals("", StringUtils.urlDecode("", ""));
323     assertEquals("", StringUtils.urlDecode("", ";,"));
324
325     // = not in the list for encoding
326     assertEquals("a%3Db", StringUtils.urlDecode("a%3Db", ";,"));
327
328     // decode = and ; but not .
329     assertEquals("a=b%3Ec; d",
330             StringUtils.urlDecode("a%3Db%3Ec; d", ";=,"));
331
332     // space not in the list for decoding
333     assertEquals("a=b;c+d", StringUtils.urlDecode("a%3Db%3Bc+d", ";=,"));
334
335     // decode space also; %3E is not decoded to .
336     assertEquals("a=b%3Ec d=,",
337             StringUtils.urlDecode("a%3Db%3Ec+d%3D%2C", ";=, "));
338
339     // decode encoded % (%25)
340     assertEquals("a,=;\t%z",
341             StringUtils.urlDecode("a%2C%3D%3B%09%25z", ";=,\t%"));
342   }
343 }