1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.inputmethod.latin.utils; 18 19 import android.test.AndroidTestCase; 20 import android.test.suitebuilder.annotation.SmallTest; 21 22 import com.android.inputmethod.latin.utils.CsvUtils.CsvParseException; 23 24 import java.util.Arrays; 25 26 @SmallTest 27 public class CsvUtilsTests extends AndroidTestCase { 28 public void testUnescape() { 29 assertEquals("", CsvUtils.unescapeField("")); 30 assertEquals("text", CsvUtils.unescapeField("text")); // text 31 assertEquals("", CsvUtils.unescapeField("\"\"")); // "" 32 assertEquals("\"", CsvUtils.unescapeField("\"\"\"\"")); // """" -> " 33 assertEquals("text", CsvUtils.unescapeField("\"text\"")); // "text" -> text 34 assertEquals("\"text", CsvUtils.unescapeField("\"\"\"text\"")); // """text" -> "text 35 assertEquals("text\"", CsvUtils.unescapeField("\"text\"\"\"")); // "text""" -> text" 36 assertEquals("te\"xt", CsvUtils.unescapeField("\"te\"\"xt\"")); // "te""xt" -> te"xt 37 assertEquals("\"text\"", 38 CsvUtils.unescapeField("\"\"\"text\"\"\"")); // """text""" -> "text" 39 assertEquals("t\"e\"x\"t", 40 CsvUtils.unescapeField("\"t\"\"e\"\"x\"\"t\"")); // "t""e""x""t" -> t"e"x"t 41 } 42 43 public void testUnescapeException() { 44 try { 45 final String text = CsvUtils.unescapeField("\""); // " 46 fail("Unterminated quote: text=" + text); 47 } catch (final CsvParseException success) { 48 assertEquals("Unterminated quote", success.getMessage()); 49 } 50 try { 51 final String text = CsvUtils.unescapeField("\"\"\""); // """ 52 fail("Unterminated quote: text=" + text); 53 } catch (final CsvParseException success) { 54 assertEquals("Unterminated quote", success.getMessage()); 55 } 56 try { 57 final String text = CsvUtils.unescapeField("\"\"\"\"\""); // """"" 58 fail("Unterminated quote: text=" + text); 59 } catch (final CsvParseException success) { 60 assertEquals("Unterminated quote", success.getMessage()); 61 } 62 try { 63 final String text = CsvUtils.unescapeField("\"text"); // "text 64 fail("Unterminated quote: text=" + text); 65 } catch (final CsvParseException success) { 66 assertEquals("Unterminated quote", success.getMessage()); 67 } 68 try { 69 final String text = CsvUtils.unescapeField("text\""); // text" 70 fail("Raw quote in text: text=" + text); 71 } catch (final CsvParseException success) { 72 assertEquals("Raw quote in text", success.getMessage()); 73 } 74 try { 75 final String text = CsvUtils.unescapeField("te\"xt"); // te"xt 76 fail("Raw quote in text: text=" + text); 77 } catch (final CsvParseException success) { 78 assertEquals("Raw quote in text", success.getMessage()); 79 } 80 try { 81 final String text = CsvUtils.unescapeField("\"\"text"); // ""text 82 fail("Raw quote in quoted text: text=" + text); 83 } catch (final CsvParseException success) { 84 assertEquals("Raw quote in quoted text", success.getMessage()); 85 } 86 try { 87 final String text = CsvUtils.unescapeField("text\"\""); // text"" 88 fail("Escaped quote in text: text=" + text); 89 } catch (final CsvParseException success) { 90 assertEquals("Escaped quote in text", success.getMessage()); 91 } 92 try { 93 final String text = CsvUtils.unescapeField("te\"\"xt"); // te""xt 94 fail("Escaped quote in text: text=" + text); 95 } catch (final CsvParseException success) { 96 assertEquals("Escaped quote in text", success.getMessage()); 97 } 98 try { 99 final String text = CsvUtils.unescapeField("\"\"text\""); // ""text" 100 fail("Raw quote in quoted text: text=" + text); 101 } catch (final CsvParseException success) { 102 assertEquals("Raw quote in quoted text", success.getMessage()); 103 } 104 try { 105 final String text = CsvUtils.unescapeField("\"text\"\""); // "text"" 106 fail("Unterminated quote: text=" + text); 107 } catch (final CsvParseException success) { 108 assertEquals("Unterminated quote", success.getMessage()); 109 } 110 try { 111 final String text = CsvUtils.unescapeField("\"te\"xt\""); // "te"xt" 112 fail("Raw quote in quoted text: text=" + text); 113 } catch (final CsvParseException success) { 114 assertEquals("Raw quote in quoted text", success.getMessage()); 115 } 116 try { 117 final String text = CsvUtils.unescapeField("\"b,c"); // "b,c 118 fail("Unterminated quote: text=" + text); 119 } catch (final CsvParseException success) { 120 assertEquals("Unterminated quote", success.getMessage()); 121 } 122 try { 123 final String text = CsvUtils.unescapeField("\",\"a\""); // ","a" 124 fail("Raw quote in quoted text: text=" + text); 125 } catch (final CsvParseException success) { 126 assertEquals("Raw quote in quoted text", success.getMessage()); 127 } 128 } 129 130 private static <T> void assertArrayEquals(final T[] expected, final T[] actual) { 131 if (expected == actual) { 132 return; 133 } 134 if (expected == null || actual == null) { 135 assertEquals(Arrays.toString(expected), Arrays.toString(actual)); 136 return; 137 } 138 if (expected.length != actual.length) { 139 assertEquals("[length]", Arrays.toString(expected), Arrays.toString(actual)); 140 return; 141 } 142 for (int i = 0; i < expected.length; i++) { 143 final T e = expected[i]; 144 final T a = actual[i]; 145 if (e == a) { 146 continue; 147 } 148 assertEquals("["+i+"]", expected[i], actual[i]); 149 } 150 } 151 152 public void testSplit() { 153 assertArrayEquals(new String[]{""}, CsvUtils.split("")); 154 assertArrayEquals(new String[]{" "}, CsvUtils.split(" ")); 155 assertArrayEquals(new String[]{"text"}, CsvUtils.split("text")); 156 assertArrayEquals(new String[]{" a b "}, CsvUtils.split(" a b ")); 157 158 assertArrayEquals(new String[]{"", ""}, CsvUtils.split(",")); 159 assertArrayEquals(new String[]{"", "", ""}, CsvUtils.split(",,")); 160 assertArrayEquals(new String[]{" ", " "}, CsvUtils.split(" , ")); 161 assertArrayEquals(new String[]{" ", " ", " "}, CsvUtils.split(" , , ")); 162 assertArrayEquals(new String[]{"a", "b"}, CsvUtils.split("a,b")); 163 assertArrayEquals(new String[]{" a ", " b "}, CsvUtils.split(" a , b ")); 164 165 assertArrayEquals(new String[]{"text"}, 166 CsvUtils.split("\"text\"")); // "text" 167 assertArrayEquals(new String[]{" text "}, 168 CsvUtils.split("\" text \"")); // "_text_" 169 170 assertArrayEquals(new String[]{""}, 171 CsvUtils.split("\"\"")); // "" 172 assertArrayEquals(new String[]{"\""}, 173 CsvUtils.split("\"\"\"\"")); // """" 174 assertArrayEquals(new String[]{"", ""}, 175 CsvUtils.split("\"\",\"\"")); // "","" 176 assertArrayEquals(new String[]{"\",\""}, 177 CsvUtils.split("\"\"\",\"\"\"")); // """,""" 178 assertArrayEquals(new String[]{"\"", "\""}, 179 CsvUtils.split("\"\"\"\",\"\"\"\"")); // """","""" 180 assertArrayEquals(new String[]{"\"", "\",\""}, 181 CsvUtils.split("\"\"\"\",\"\"\",\"\"\"")); // """",""",""" 182 assertArrayEquals(new String[]{"\",\"", "\""}, 183 CsvUtils.split("\"\"\",\"\"\",\"\"\"\"")); // """,""","""" 184 185 assertArrayEquals(new String[]{" a ", " b , c "}, 186 CsvUtils.split(" a ,\" b , c \"")); // _a_,"_b_,_c_" 187 assertArrayEquals(new String[]{" a ", " b , c ", " d "}, 188 CsvUtils.split(" a ,\" b , c \", d ")); // _a_,"_b_,_c_",_d_ 189 } 190 191 public void testSplitException() { 192 try { 193 final String[] fields = CsvUtils.split(" \"text\" "); // _"text"_ 194 fail("Raw quote in text: fields=" + Arrays.toString(fields)); 195 } catch (final CsvParseException success) { 196 assertEquals("Raw quote in text", success.getMessage()); 197 } 198 try { 199 final String[] fields = CsvUtils.split(" \" text \" "); // _"_text_"_ 200 fail("Raw quote in text: fields=" + Arrays.toString(fields)); 201 } catch (final CsvParseException success) { 202 assertEquals("Raw quote in text", success.getMessage()); 203 } 204 205 try { 206 final String[] fields = CsvUtils.split("a,\"b,"); // a,",b 207 fail("Unterminated quote: fields=" + Arrays.toString(fields)); 208 } catch (final CsvParseException success) { 209 assertEquals("Unterminated quote", success.getMessage()); 210 } 211 try { 212 final String[] fields = CsvUtils.split("a,\"\"\",b"); // a,""",b 213 fail("Unterminated quote: fields=" + Arrays.toString(fields)); 214 } catch (final CsvParseException success) { 215 assertEquals("Unterminated quote", success.getMessage()); 216 } 217 try { 218 final String[] fields = CsvUtils.split("a,\"\"\"\"\",b"); // a,""""",b 219 fail("Unterminated quote: fields=" + Arrays.toString(fields)); 220 } catch (final CsvParseException success) { 221 assertEquals("Unterminated quote", success.getMessage()); 222 } 223 try { 224 final String[] fields = CsvUtils.split("a,\"b,c"); // a,"b,c 225 fail("Unterminated quote: fields=" + Arrays.toString(fields)); 226 } catch (final CsvParseException success) { 227 assertEquals("Unterminated quote", success.getMessage()); 228 } 229 try { 230 final String[] fields = CsvUtils.split("a,\",\"b,c"); // a,","b,c 231 fail("Raw quote in quoted text: fields=" + Arrays.toString(fields)); 232 } catch (final CsvParseException success) { 233 assertEquals("Raw quote in quoted text", success.getMessage()); 234 } 235 try { 236 final String[] fields = CsvUtils.split("a,\",\"b\",\",c"); // a,","b",",c 237 fail("Raw quote in quoted text: fields=" + Arrays.toString(fields)); 238 } catch (final CsvParseException success) { 239 assertEquals("Raw quote in quoted text", success.getMessage()); 240 } 241 } 242 243 public void testSplitWithTrimSpaces() { 244 final int trimSpaces = CsvUtils.SPLIT_FLAGS_TRIM_SPACES; 245 assertArrayEquals(new String[]{""}, CsvUtils.split(trimSpaces, "")); 246 assertArrayEquals(new String[]{""}, CsvUtils.split(trimSpaces, " ")); 247 assertArrayEquals(new String[]{"text"}, CsvUtils.split(trimSpaces, "text")); 248 assertArrayEquals(new String[]{"a b"}, CsvUtils.split(trimSpaces, " a b ")); 249 250 assertArrayEquals(new String[]{"", ""}, CsvUtils.split(trimSpaces, ",")); 251 assertArrayEquals(new String[]{"", "", ""}, CsvUtils.split(trimSpaces, ",,")); 252 assertArrayEquals(new String[]{"", ""}, CsvUtils.split(trimSpaces, " , ")); 253 assertArrayEquals(new String[]{"", "", ""}, CsvUtils.split(trimSpaces, " , , ")); 254 assertArrayEquals(new String[]{"a", "b"}, CsvUtils.split(trimSpaces, "a,b")); 255 assertArrayEquals(new String[]{"a", "b"}, CsvUtils.split(trimSpaces, " a , b ")); 256 257 assertArrayEquals(new String[]{"text"}, 258 CsvUtils.split(trimSpaces, "\"text\"")); // "text" 259 assertArrayEquals(new String[]{"text"}, 260 CsvUtils.split(trimSpaces, " \"text\" ")); // _"text"_ 261 assertArrayEquals(new String[]{" text "}, 262 CsvUtils.split(trimSpaces, "\" text \"")); // "_text_" 263 assertArrayEquals(new String[]{" text "}, 264 CsvUtils.split(trimSpaces, " \" text \" ")); // _"_text_"_ 265 assertArrayEquals(new String[]{"a", "b"}, 266 CsvUtils.split(trimSpaces, " \"a\" , \"b\" ")); // _"a"_,_"b"_ 267 268 assertArrayEquals(new String[]{""}, 269 CsvUtils.split(trimSpaces, " \"\" ")); // _""_ 270 assertArrayEquals(new String[]{"\""}, 271 CsvUtils.split(trimSpaces, " \"\"\"\" ")); // _""""_ 272 assertArrayEquals(new String[]{"", ""}, 273 CsvUtils.split(trimSpaces, " \"\" , \"\" ")); // _""_,_""_ 274 assertArrayEquals(new String[]{"\" , \""}, 275 CsvUtils.split(trimSpaces, " \"\"\" , \"\"\" ")); // _"""_,_"""_ 276 assertArrayEquals(new String[]{"\"", "\""}, 277 CsvUtils.split(trimSpaces, " \"\"\"\" , \"\"\"\" ")); // _""""_,_""""_ 278 assertArrayEquals(new String[]{"\"", "\" , \""}, 279 CsvUtils.split(trimSpaces, " \"\"\"\" , \"\"\" , \"\"\" ")); // _""""_,_"""_,_"""_ 280 assertArrayEquals(new String[]{"\" , \"", "\""}, 281 CsvUtils.split(trimSpaces, " \"\"\" , \"\"\" , \"\"\"\" ")); // _"""_,_"""_,_""""_ 282 283 assertArrayEquals(new String[]{"a", " b , c "}, 284 CsvUtils.split(trimSpaces, " a , \" b , c \" ")); // _a_,_"_b_,_c_"_ 285 assertArrayEquals(new String[]{"a", " b , c ", "d"}, 286 CsvUtils.split(trimSpaces, " a, \" b , c \" , d ")); // _a,_"_b_,_c_"_,_d_ 287 } 288 289 public void testEscape() { 290 assertEquals("", CsvUtils.escapeField("", false)); 291 assertEquals("plain", CsvUtils.escapeField("plain", false)); 292 assertEquals(" ", CsvUtils.escapeField(" ", false)); 293 assertEquals(" ", CsvUtils.escapeField(" ", false)); 294 assertEquals("a space", CsvUtils.escapeField("a space", false)); 295 assertEquals(" space-at-start", CsvUtils.escapeField(" space-at-start", false)); 296 assertEquals("space-at-end ", CsvUtils.escapeField("space-at-end ", false)); 297 assertEquals("a lot of spaces", CsvUtils.escapeField("a lot of spaces", false)); 298 assertEquals("\",\"", CsvUtils.escapeField(",", false)); 299 assertEquals("\",,\"", CsvUtils.escapeField(",,", false)); 300 assertEquals("\"a,comma\"", CsvUtils.escapeField("a,comma", false)); 301 assertEquals("\",comma-at-begin\"", CsvUtils.escapeField(",comma-at-begin", false)); 302 assertEquals("\"comma-at-end,\"", CsvUtils.escapeField("comma-at-end,", false)); 303 assertEquals("\",,a,lot,,,of,commas,,\"", 304 CsvUtils.escapeField(",,a,lot,,,of,commas,,", false)); 305 assertEquals("\"a comma,and a space\"", CsvUtils.escapeField("a comma,and a space", false)); 306 assertEquals("\"\"\"\"", CsvUtils.escapeField("\"", false)); // " -> """" 307 assertEquals("\"\"\"\"\"\"", CsvUtils.escapeField("\"\"", false)); // "" -> """""" 308 assertEquals("\"\"\"\"\"\"\"\"", CsvUtils.escapeField("\"\"\"", false)); // """ -> """""""" 309 assertEquals("\"\"\"text\"\"\"", 310 CsvUtils.escapeField("\"text\"", false)); // "text" -> """text""" 311 assertEquals("\"text has \"\" in middle\"", 312 CsvUtils.escapeField("text has \" in middle", false)); 313 assertEquals("\"\"\"quote,at begin\"", CsvUtils.escapeField("\"quote,at begin", false)); 314 assertEquals("\"quote at,end\"\"\"", CsvUtils.escapeField("quote at,end\"", false)); 315 assertEquals("\"\"\"quote at begin\"", CsvUtils.escapeField("\"quote at begin", false)); 316 assertEquals("\"quote at end\"\"\"", CsvUtils.escapeField("quote at end\"", false)); 317 } 318 319 public void testEscapeWithAlwaysQuoted() { 320 assertEquals("\"\"", CsvUtils.escapeField("", true)); 321 assertEquals("\"plain\"", CsvUtils.escapeField("plain", true)); 322 assertEquals("\" \"", CsvUtils.escapeField(" ", true)); 323 assertEquals("\" \"", CsvUtils.escapeField(" ", true)); 324 assertEquals("\"a space\"", CsvUtils.escapeField("a space", true)); 325 assertEquals("\" space-at-start\"", CsvUtils.escapeField(" space-at-start", true)); 326 assertEquals("\"space-at-end \"", CsvUtils.escapeField("space-at-end ", true)); 327 assertEquals("\"a lot of spaces\"", CsvUtils.escapeField("a lot of spaces", true)); 328 assertEquals("\",\"", CsvUtils.escapeField(",", true)); 329 assertEquals("\",,\"", CsvUtils.escapeField(",,", true)); 330 assertEquals("\"a,comma\"", CsvUtils.escapeField("a,comma", true)); 331 assertEquals("\",comma-at-begin\"", CsvUtils.escapeField(",comma-at-begin", true)); 332 assertEquals("\"comma-at-end,\"", CsvUtils.escapeField("comma-at-end,", true)); 333 assertEquals("\",,a,lot,,,of,commas,,\"", 334 CsvUtils.escapeField(",,a,lot,,,of,commas,,", true)); 335 assertEquals("\"a comma,and a space\"", CsvUtils.escapeField("a comma,and a space", true)); 336 assertEquals("\"\"\"\"", CsvUtils.escapeField("\"", true)); // " -> """" 337 assertEquals("\"\"\"\"\"\"", CsvUtils.escapeField("\"\"", true)); // "" -> """""" 338 assertEquals("\"\"\"\"\"\"\"\"", CsvUtils.escapeField("\"\"\"", true)); // """ -> """""""" 339 assertEquals("\"\"\"text\"\"\"", 340 CsvUtils.escapeField("\"text\"", true)); // "text" -> """text""" 341 assertEquals("\"text has \"\" in middle\"", 342 CsvUtils.escapeField("text has \" in middle", true)); 343 assertEquals("\"\"\"quote,at begin\"", CsvUtils.escapeField("\"quote,at begin", true)); 344 assertEquals("\"quote at,end\"\"\"", CsvUtils.escapeField("quote at,end\"", true)); 345 assertEquals("\"\"\"quote at begin\"", CsvUtils.escapeField("\"quote at begin", true)); 346 assertEquals("\"quote at end\"\"\"", CsvUtils.escapeField("quote at end\"", true)); 347 } 348 349 public void testJoinWithoutColumnPositions() { 350 assertEquals("", CsvUtils.join()); 351 assertEquals("", CsvUtils.join("")); 352 assertEquals(",", CsvUtils.join("", "")); 353 354 assertEquals("text, text,text ", 355 CsvUtils.join("text", " text", "text ")); 356 assertEquals("\"\"\"\",\"\"\"\"\"\",\"\"\"text\"\"\"", 357 CsvUtils.join("\"", "\"\"", "\"text\"")); 358 assertEquals("a b,\"c,d\",\"e\"\"f\"", 359 CsvUtils.join("a b", "c,d", "e\"f")); 360 } 361 362 public void testJoinWithoutColumnPositionsWithExtraSpace() { 363 final int extraSpace = CsvUtils.JOIN_FLAGS_EXTRA_SPACE; 364 assertEquals("", CsvUtils.join(extraSpace)); 365 assertEquals("", CsvUtils.join(extraSpace, "")); 366 assertEquals(", ", CsvUtils.join(extraSpace, "", "")); 367 368 assertEquals("text, text, text ", 369 CsvUtils.join(extraSpace, "text", " text", "text ")); 370 // ","","text" -> """","""""","""text""" 371 assertEquals("\"\"\"\", \"\"\"\"\"\", \"\"\"text\"\"\"", 372 CsvUtils.join(extraSpace, "\"", "\"\"", "\"text\"")); 373 assertEquals("a b, \"c,d\", \"e\"\"f\"", 374 CsvUtils.join(extraSpace, "a b", "c,d", "e\"f")); 375 } 376 377 public void testJoinWithoutColumnPositionsWithExtraSpaceAndAlwaysQuoted() { 378 final int extrSpaceAndQuoted = 379 CsvUtils.JOIN_FLAGS_EXTRA_SPACE | CsvUtils.JOIN_FLAGS_ALWAYS_QUOTED; 380 assertEquals("", CsvUtils.join(extrSpaceAndQuoted)); 381 assertEquals("\"\"", CsvUtils.join(extrSpaceAndQuoted, "")); 382 assertEquals("\"\", \"\"", CsvUtils.join(extrSpaceAndQuoted, "", "")); 383 384 assertEquals("\"text\", \" text\", \"text \"", 385 CsvUtils.join(extrSpaceAndQuoted, "text", " text", "text ")); 386 // ","","text" -> """", """""", """text""" 387 assertEquals("\"\"\"\", \"\"\"\"\"\", \"\"\"text\"\"\"", 388 CsvUtils.join(extrSpaceAndQuoted, "\"", "\"\"", "\"text\"")); 389 assertEquals("\"a b\", \"c,d\", \"e\"\"f\"", 390 CsvUtils.join(extrSpaceAndQuoted, "a b", "c,d", "e\"f")); 391 } 392 393 public void testJoinWithColumnPositions() { 394 final int noFlags = CsvUtils.JOIN_FLAGS_NONE; 395 assertEquals("", CsvUtils.join(noFlags, new int[]{})); 396 assertEquals(" ", CsvUtils.join(noFlags, new int[]{3}, "")); 397 assertEquals(" ,", CsvUtils.join(noFlags, new int[]{1}, "", "")); 398 assertEquals(", ", CsvUtils.join(noFlags, new int[]{0, 3}, "", "")); 399 400 assertEquals("text, text, text ", 401 CsvUtils.join(noFlags, new int[]{0, 8, 15}, "text", " text", "text ")); 402 // ","","text" -> """", """""","""text""" 403 assertEquals("\"\"\"\", \"\"\"\"\"\",\"\"\"text\"\"\"", 404 CsvUtils.join(noFlags, new int[]{0, 8, 15}, "\"", "\"\"", "\"text\"")); 405 assertEquals("a b, \"c,d\", \"e\"\"f\"", 406 CsvUtils.join(noFlags, new int[]{0, 8, 15}, "a b", "c,d", "e\"f")); 407 } 408 409 public void testJoinWithColumnPositionsWithExtraSpace() { 410 final int extraSpace = CsvUtils.JOIN_FLAGS_EXTRA_SPACE; 411 assertEquals("", CsvUtils.join(extraSpace, new int[]{})); 412 assertEquals(" ", CsvUtils.join(extraSpace, new int[]{3}, "")); 413 assertEquals(" , ", CsvUtils.join(extraSpace, new int[]{1}, "", "")); 414 assertEquals(", ", CsvUtils.join(extraSpace, new int[]{0, 3}, "", "")); 415 416 assertEquals("text, text, text ", 417 CsvUtils.join(extraSpace, new int[]{0, 8, 15}, "text", " text", "text ")); 418 // ","","text" -> """", """""", """text""" 419 assertEquals("\"\"\"\", \"\"\"\"\"\", \"\"\"text\"\"\"", 420 CsvUtils.join(extraSpace, new int[]{0, 8, 15}, "\"", "\"\"", "\"text\"")); 421 assertEquals("a b, \"c,d\", \"e\"\"f\"", 422 CsvUtils.join(extraSpace, new int[]{0, 8, 15}, "a b", "c,d", "e\"f")); 423 } 424 } 425