Home | History | Annotate | Download | only in utils
      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