1: %% -*- coding: utf-8 -*-
    2: %%
    3: %% %CopyrightBegin%
    4: %% 
    5: %% Copyright Ericsson AB 2004-2012. All Rights Reserved.
    6: %% 
    7: %% The contents of this file are subject to the Erlang Public License,
    8: %% Version 1.1, (the "License"); you may not use this file except in
    9: %% compliance with the License. You should have received a copy of the
   10: %% Erlang Public License along with this software. If not, it can be
   11: %% retrieved online at http://www.erlang.org/.
   12: %% 
   13: %% Software distributed under the License is distributed on an "AS IS"
   14: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
   15: %% the License for the specific language governing rights and limitations
   16: %% under the License.
   17: %% 
   18: %% %CopyrightEnd%
   19: %%
   20: %%%----------------------------------------------------------------
   21: %%% Purpose: string test suite.
   22: %%%-----------------------------------------------------------------
   23: -module(string_SUITE).
   24: -include_lib("test_server/include/test_server.hrl").
   25: 
   26: 
   27: % Default timetrap timeout (set in init_per_testcase).
   28: -define(default_timeout, ?t:minutes(1)).
   29: 
   30: % Test server specific exports
   31: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 
   32: 	 init_per_group/2,end_per_group/2]).
   33: -export([init_per_testcase/2, end_per_testcase/2]).
   34: 
   35: % Test cases must be exported.
   36: -export([len/1,equal/1,concat/1,chr_rchr/1,str_rstr/1]).
   37: -export([span_cspan/1,substr/1,tokens/1,chars/1]).
   38: -export([copies/1,words/1,strip/1,sub_word/1,left_right/1]).
   39: -export([sub_string/1,centre/1, join/1]).
   40: -export([to_integer/1,to_float/1]).
   41: -export([to_upper_to_lower/1]).
   42: %%
   43: %% all/1
   44: %%
   45: suite() -> [{ct_hooks,[ts_install_cth]}].
   46: 
   47: all() -> 
   48:     [len, equal, concat, chr_rchr, str_rstr, span_cspan,
   49:      substr, tokens, chars, copies, words, strip, sub_word,
   50:      left_right, sub_string, centre, join, to_integer,
   51:      to_float, to_upper_to_lower].
   52: 
   53: groups() -> 
   54:     [].
   55: 
   56: init_per_suite(Config) ->
   57:     Config.
   58: 
   59: end_per_suite(_Config) ->
   60:     ok.
   61: 
   62: init_per_group(_GroupName, Config) ->
   63:     Config.
   64: 
   65: end_per_group(_GroupName, Config) ->
   66:     Config.
   67: 
   68: 
   69: init_per_testcase(_Case, Config) ->
   70:     ?line Dog=test_server:timetrap(?default_timeout),
   71:     [{watchdog, Dog}|Config].
   72: end_per_testcase(_Case, Config) ->
   73:     Dog=?config(watchdog, Config),
   74:     test_server:timetrap_cancel(Dog),
   75:     ok.
   76: 
   77: %
   78: % Test cases starts here.
   79: %
   80: 
   81: len(suite) ->
   82:     [];
   83: len(doc) ->
   84:     [];
   85: len(Config) when is_list(Config) ->
   86:     ?line 0 = string:len(""),
   87:     ?line L = tuple_size(list_to_tuple(atom_to_list(?MODULE))),
   88:     ?line L = string:len(atom_to_list(?MODULE)),
   89:     %% invalid arg type
   90:     ?line {'EXIT',_} = (catch string:len({})),
   91:     ok.
   92: 
   93: equal(suite) ->
   94:     [];
   95: equal(doc) ->
   96:     [];
   97: equal(Config) when is_list(Config) ->
   98:     ?line true = string:equal("", ""),
   99:     ?line false = string:equal("", " "),
  100:     ?line true = string:equal("laban", "laban"),
  101:     ?line false = string:equal("skvimp", "skvump"),
  102:     %% invalid arg type
  103:     ?line true = string:equal(2, 2),			% not good, should crash
  104:     ok.
  105: 
  106: concat(suite) ->
  107:     [];
  108: concat(doc) ->
  109:     [];
  110: concat(Config) when is_list(Config) ->
  111:     ?line "erlang rules" = string:concat("erlang ", "rules"),
  112:     ?line "" = string:concat("", ""),
  113:     ?line "x" = string:concat("x", ""),
  114:     ?line "y" = string:concat("", "y"),
  115:     %% invalid arg type
  116:     ?line {'EXIT',_} = (catch string:concat(hello, please)),
  117:     ok.
  118: 
  119: chr_rchr(suite) ->
  120:     [];
  121: chr_rchr(doc) ->
  122:     [];
  123: chr_rchr(Config) when is_list(Config) ->
  124:     ?line {_,_,X} = now(),
  125:     ?line 0 = string:chr("", (X rem (255-32)) + 32),
  126:     ?line 0 = string:rchr("", (X rem (255-32)) + 32),
  127:     ?line 1 = string:chr("x", $x),
  128:     ?line 1 = string:rchr("x", $x),
  129:     ?line 1 = string:chr("xx", $x),
  130:     ?line 2 = string:rchr("xx", $x),
  131:     ?line 3 = string:chr("xyzyx", $z),
  132:     ?line 3 = string:rchr("xyzyx", $z),
  133:     %% invalid arg type
  134:     ?line {'EXIT',_} = (catch string:chr(hello, $h)),
  135:     %% invalid arg type
  136:     ?line {'EXIT',_} = (catch string:chr("hello", h)),
  137:     %% invalid arg type
  138:     ?line {'EXIT',_} = (catch string:rchr(hello, $h)),
  139:     %% invalid arg type
  140:     ?line {'EXIT',_} = (catch string:rchr("hello", h)),
  141:     ok.
  142: 
  143: str_rstr(suite) ->
  144:     [];
  145: str_rstr(doc) ->
  146:     [];
  147: str_rstr(Config) when is_list(Config) ->
  148:     ?line {_,_,X} = now(),
  149:     ?line 0 = string:str("", [(X rem (255-32)) + 32]),
  150:     ?line 0 = string:rstr("", [(X rem (255-32)) + 32]),
  151:     ?line 1 = string:str("x", "x"),
  152:     ?line 1 = string:rstr("x", "x"),
  153:     ?line 0 = string:str("hello", ""),
  154:     ?line 0 = string:rstr("hello", ""),
  155:     ?line 1 = string:str("xxxx", "xx"),
  156:     ?line 3 = string:rstr("xxxx", "xx"),
  157:     ?line 3 = string:str("xy z yx", " z"),
  158:     ?line 3 = string:rstr("xy z yx", " z"),
  159:     %% invalid arg type
  160:     ?line {'EXIT',_} = (catch string:str(hello, "he")),
  161:     %% invalid arg type
  162:     ?line {'EXIT',_} = (catch string:str("hello", he)),
  163:     %% invalid arg type
  164:     ?line {'EXIT',_} = (catch string:rstr(hello, "he")),
  165:     %% invalid arg type
  166:     ?line {'EXIT',_} = (catch string:rstr("hello", he)),
  167:     ok.
  168: 
  169: span_cspan(suite) ->
  170:     [];
  171: span_cspan(doc) ->
  172:     [];
  173: span_cspan(Config) when is_list(Config) ->
  174:     ?line 0 = string:span("", "1"),
  175:     ?line 0 = string:span("1", ""),
  176:     ?line 0 = string:cspan("", "1"),
  177:     ?line 1 = string:cspan("1", ""),
  178:     ?line 1 = string:span("1  ", "1"),
  179:     ?line 5 = string:span("  1  ", "12 "),
  180:     ?line 6 = string:span("1231234", "123"),
  181:     ?line 0 = string:cspan("1  ", "1"),
  182:     ?line 1 = string:cspan("3 ", "12 "),
  183:     ?line 6 = string:cspan("1231234", "4"),
  184:     %% invalid arg type
  185:     ?line {'EXIT',_} = (catch string:span(1234, "1")),
  186:     %% invalid arg type
  187:     ?line {'EXIT',_} = (catch string:span(1234, "1")),
  188:     %% invalid arg type
  189:     ?line {'EXIT',_} = (catch string:cspan("1234", 1)),
  190:     %% invalid arg type
  191:     ?line {'EXIT',_} = (catch string:cspan("1234", 4)),
  192:     ok.
  193: 
  194: 
  195: substr(suite) ->
  196:     [];
  197: substr(doc) ->
  198:     [];
  199: substr(Config) when is_list(Config) ->
  200:     ?line {'EXIT',_} = (catch string:substr("", 0)), 
  201:     ?line [] = string:substr("", 1), 
  202:     ?line {'EXIT',_} = (catch string:substr("", 2)), 
  203:     ?line [] = string:substr("1", 2), 
  204:     ?line {'EXIT',_} = (catch  string:substr("", 0, 1)), 
  205:     ?line [] = string:substr("", 1, 1), 
  206:     ?line [] = string:substr("", 1, 2), 
  207:     ?line {'EXIT',_} = (catch string:substr("", 2, 2)),
  208:     ?line "1234" = string:substr("1234", 1), 
  209:     ?line "1234" = string:substr("1234", 1, 4), 
  210:     ?line "1234" = string:substr("1234", 1, 5), 
  211:     ?line "23" = string:substr("1234", 2, 2), 
  212:     ?line "4" = string:substr("1234", 4), 
  213:     ?line "" = string:substr("1234", 4, 0), 
  214:     ?line "4" = string:substr("1234", 4, 1), 
  215:     %% invalid arg type
  216:     ?line {'EXIT',_} = (catch string:substr(1234, 1)),
  217:     %% invalid arg type
  218:     ?line {'EXIT',_} = (catch string:substr("1234", "1")),
  219:     ok.
  220: 
  221: tokens(suite) ->
  222:     [];
  223: tokens(doc) ->
  224:     [];
  225: tokens(Config) when is_list(Config) ->
  226:     ?line [] = string:tokens("",""),
  227:     ?line [] = string:tokens("abc","abc"),
  228:     ?line ["abc"] = string:tokens("abc", ""),
  229:     ?line ["1","2 34","4","5"] = string:tokens("1,2 34,4;5", ";,"),
  230:     %% invalid arg type
  231:     ?line {'EXIT',_} = (catch string:tokens('x,y', ",")), 
  232:     %% invalid arg type
  233:     ?line {'EXIT',_} = (catch string:tokens("x,y", ',')), 
  234:     ok.
  235: 
  236: 
  237: chars(suite) ->
  238:     [];
  239: chars(doc) ->
  240:     [];
  241: chars(Config) when is_list(Config) ->
  242:     ?line [] = string:chars($., 0),
  243:     ?line [] = string:chars($., 0, []),
  244:     ?line 10 = length(string:chars(32, 10, [])),
  245:     ?line "aaargh" = string:chars($a, 3, "rgh"),
  246:     %% invalid arg type
  247:     ?line {'EXIT',_} = (catch string:chars($x, [])),
  248:     ok.
  249: 
  250: copies(suite) ->
  251:     [];
  252: copies(doc) ->
  253:     [];
  254: copies(Config) when is_list(Config) ->
  255:     ?line "" = string:copies("", 10),
  256:     ?line "" = string:copies(".", 0),
  257:     ?line "." = string:copies(".", 1),
  258:     ?line 30 = length(string:copies("123", 10)),
  259:     %% invalid arg type
  260:     ?line {'EXIT',_} = (catch string:copies("hej", -1)),
  261:     ?line {'EXIT',_} = (catch string:copies("hej", 2.0)),
  262:     ok.
  263: 
  264: words(suite) ->
  265:     [];
  266: words(doc) ->
  267:     [];
  268: words(Config) when is_list(Config) ->
  269:     ?line 1 = string:words(""),
  270:     ?line 1 = string:words("", $,),
  271:     ?line 1 = string:words("hello"),
  272:     ?line 1 = string:words("hello", $,),
  273:     ?line 1 = string:words("...", $.),
  274:     ?line 2 = string:words("2.35", $.),
  275:     ?line 100 = string:words(string:copies(". ", 100)),
  276:     %% invalid arg type
  277:     ?line {'EXIT',_} = (catch string:chars(hej, 1)),
  278:     %% invalid arg type
  279:     ?line {'EXIT',_} = (catch string:chars("hej", 1, " ")),
  280:     ok.
  281: 
  282: 
  283: strip(suite) ->
  284:     [];
  285: strip(doc) ->
  286:     [];
  287: strip(Config) when is_list(Config) ->
  288:     ?line "" = string:strip(""),
  289:     ?line "" = string:strip("", both),  
  290:     ?line "" = string:strip("", both, $.),  
  291:     ?line "hej" = string:strip("  hej  "),  
  292:     ?line "hej  " = string:strip("  hej  ", left),
  293:     ?line "  hej" = string:strip("  hej  ", right),
  294:     ?line "  hej  " = string:strip("  hej  ", right, $.),
  295:     ?line "hej  hopp" = string:strip("  hej  hopp  ", both),
  296:     %% invalid arg type
  297:     ?line {'EXIT',_} = (catch string:strip(hej)),
  298:     %% invalid arg type
  299:     ?line {'EXIT',_} = (catch string:strip(" hej", up)),
  300:     %% invalid arg type
  301:     ?line {'EXIT',_} = (catch string:strip(" hej", left, " ")),	% not good
  302:     ok.
  303: 
  304: sub_word(suite) ->
  305:     [];
  306: sub_word(doc) ->
  307:     [];
  308: sub_word(Config) when is_list(Config) ->
  309:     ?line "" = string:sub_word("", 1),
  310:     ?line "" = string:sub_word("", 1, $,),
  311:     ?line {'EXIT',_} = (catch string:sub_word("1 2 3", 0)),
  312:     ?line "" = string:sub_word("1 2 3", 4),
  313:     ?line "llo th" = string:sub_word("but hello there", 2, $e),
  314:     %% invalid arg type
  315:     ?line {'EXIT',_} = (catch string:sub_word('hello there', 1)),
  316:     %% invalid arg type
  317:     ?line {'EXIT',_} = (catch string:sub_word("hello there", 1, "e")),
  318:     ok.
  319: 
  320: left_right(suite) ->
  321:     [];
  322: left_right(doc) ->
  323:     [];
  324: left_right(Config) when is_list(Config) ->
  325:     ?line "" = string:left("", 0),
  326:     ?line "" = string:left("hej", 0),
  327:     ?line "" = string:left("hej", 0, $.),
  328:     ?line "" = string:right("", 0),
  329:     ?line "" = string:right("hej", 0),
  330:     ?line "" = string:right("hej", 0, $.),
  331:     ?line "123  " = string:left("123 ", 5),
  332:     ?line "  123" = string:right(" 123", 5),
  333:     ?line "123!!" = string:left("123!", 5, $!),
  334:     ?line "==123" = string:right("=123", 5, $=),
  335:     ?line "1" = string:left("123", 1, $.),
  336:     ?line "3" = string:right("123", 1, $.),
  337:     %% invalid arg type
  338:     ?line {'EXIT',_} = (catch string:left(hello, 5)),
  339:     %% invalid arg type
  340:     ?line {'EXIT',_} = (catch string:right(hello, 5)),
  341:     %% invalid arg type
  342:     ?line {'EXIT',_} = (catch string:left("hello", 5, ".")),
  343:     %% invalid arg type
  344:     ?line {'EXIT',_} = (catch string:right("hello", 5, ".")),
  345:     ok.
  346: 
  347: sub_string(suite) ->
  348:     [];
  349: sub_string(doc) ->
  350:     [];
  351: sub_string(Config) when is_list(Config) ->
  352:     ?line {'EXIT',_} = (catch string:sub_string("", 0)), 
  353:     ?line [] = string:sub_string("", 1), 
  354:     ?line {'EXIT',_} = (catch string:sub_string("", 2)), 
  355:     ?line [] = string:sub_string("1", 2), 
  356:     ?line {'EXIT',_} = (catch string:sub_string("", 0, 1)), 
  357:     ?line [] = string:sub_string("", 1, 1), 
  358:     ?line [] = string:sub_string("", 1, 2), 
  359:     ?line {'EXIT',_} = (catch string:sub_string("", 2, 2)),
  360:     ?line "1234" = string:sub_string("1234", 1), 
  361:     ?line "1234" = string:sub_string("1234", 1, 4), 
  362:     ?line "1234" = string:sub_string("1234", 1, 5), 
  363:     ?line "23" = string:sub_string("1234", 2, 3), 
  364:     ?line "4" = string:sub_string("1234", 4), 
  365:     ?line "4" = string:sub_string("1234", 4, 4), 
  366:     ?line "4" = string:sub_string("1234", 4, 5), 
  367:     %% invalid arg type
  368:     ?line {'EXIT',_} = (catch string:sub_string(1234, 1)),
  369:     %% invalid arg type
  370:     ?line {'EXIT',_} = (catch string:sub_string("1234", "1")),
  371:     ok.
  372: 
  373: centre(suite) ->
  374:     [];
  375: centre(doc) ->
  376:     [];
  377: centre(Config) when is_list(Config) ->
  378:     ?line "" = string:centre("", 0),
  379:     ?line "" = string:centre("1", 0),
  380:     ?line "" = string:centre("", 0, $-),
  381:     ?line "" = string:centre("1", 0, $-),
  382:     ?line "gd" = string:centre("agda", 2),
  383:     ?line "agda " = string:centre("agda", 5),
  384:     ?line " agda " = string:centre("agda", 6),
  385:     ?line "agda." = string:centre("agda", 5, $.),
  386:     ?line "--agda--" = string:centre("agda", 8, $-),
  387:     ?line "agda" = string:centre("agda", 4),
  388:     %% invalid arg type
  389:     ?line {'EXIT',_} = (catch string:centre(hello, 10)),
  390:     ok.
  391: 
  392: to_integer(suite) ->
  393:     [];
  394: to_integer(doc) ->
  395:     [];
  396: to_integer(Config) when is_list(Config) ->
  397:     ?line {1,""} = test_to_integer("1"),
  398:     ?line {1,""} = test_to_integer("+1"),
  399:     ?line {-1,""} = test_to_integer("-1"),
  400:     ?line {1,"="} = test_to_integer("1="),
  401:     ?line {7,"F"} = test_to_integer("7F"),
  402:     ?line {709,""} = test_to_integer("709"),
  403:     ?line {709,"*2"} = test_to_integer("709*2"),
  404:     ?line {0,"xAB"} = test_to_integer("0xAB"),
  405:     ?line {16,"#FF"} = test_to_integer("16#FF"),
  406:     ?line {error,no_integer} = test_to_integer(""),
  407:     ?line {error,no_integer} = test_to_integer("!1"),
  408:     ?line {error,no_integer} = test_to_integer("F1"),
  409:     ?line {error,not_a_list} = test_to_integer('23'),
  410:     ?line {3,[[]]} = test_to_integer([$3,[]]),
  411:     ?line {3,[hello]} = test_to_integer([$3,hello]),
  412:     ok.
  413: 
  414: test_to_integer(Str) ->
  415:     io:format("Checking ~p~n", [Str]),
  416:     case string:to_integer(Str) of
  417: 	{error,_Reason} = Bad ->
  418: 	    ?line {'EXIT',_} = (catch list_to_integer(Str)),
  419: 	    Bad;
  420: 	{F,_Rest} = Res ->
  421: 	    ?line _ = integer_to_list(F),
  422: 	    Res
  423:     end.
  424: 
  425: to_float(suite) ->
  426:     [];
  427: to_float(doc) ->
  428:     [];
  429: to_float(Config) when is_list(Config) ->
  430:     ?line {1.2,""} = test_to_float("1.2"),
  431:     ?line {1.2,""} = test_to_float("1,2"),
  432:     ?line {120.0,""} = test_to_float("1.2e2"),
  433:     ?line {120.0,""} = test_to_float("+1,2e2"),
  434:     ?line {-120.0,""} = test_to_float("-1.2e2"),
  435:     ?line {-120.0,""} = test_to_float("-1,2e+2"),
  436:     ?line {-1.2e-2,""} = test_to_float("-1.2e-2"),
  437:     ?line {1.2,"="} = test_to_float("1.2="),
  438:     ?line {7.9,"e"} = test_to_float("7.9e"),
  439:     ?line {7.9,"ee"} = test_to_float("7.9ee"),
  440:     ?line {7.9,"e+"} = test_to_float("7.9e+"),
  441:     ?line {7.9,"e-"} = test_to_float("7.9e-"),
  442:     ?line {7.9,"e++"} = test_to_float("7.9e++"),
  443:     ?line {7.9,"e--"} = test_to_float("7.9e--"),
  444:     ?line {7.9,"e+e"} = test_to_float("7.9e+e"),
  445:     ?line {7.9,"e-e"} = test_to_float("7.9e-e"),
  446:     ?line {7.9,"e+."} = test_to_float("7.9e+."),
  447:     ?line {7.9,"e-."} = test_to_float("7.9e-."),
  448:     ?line {7.9,"e+,"} = test_to_float("7.9e+,"),
  449:     ?line {7.9,"e-,"} = test_to_float("7.9e-,"),
  450:     ?line {error,no_float} = test_to_float(""),
  451:     ?line {error,no_float} = test_to_float("e1,0"),
  452:     ?line {error,no_float} = test_to_float("1;0"),
  453:     ?line {error,no_float} = test_to_float("1"),
  454:     ?line {error,no_float} = test_to_float("1e"),
  455:     ?line {error,no_float} = test_to_float("2."),
  456:     ?line {error,not_a_list} = test_to_float('2.3'),
  457:     ?line {2.3,[[]]} = test_to_float([$2,$.,$3,[]]),
  458:     ?line {2.3,[hello]} = test_to_float([$2,$.,$3,hello]),
  459:     ok.
  460: 
  461: test_to_float(Str) ->
  462:     io:format("Checking ~p~n", [Str]),
  463:     case string:to_float(Str) of
  464: 	{error,_Reason} = Bad ->
  465: 	    ?line {'EXIT',_} = (catch list_to_float(Str)),
  466: 	    Bad;
  467: 	{F,_Rest} = Res ->
  468: 	    ?line _ = float_to_list(F),
  469: 	    Res
  470:     end.
  471: 	    
  472: to_upper_to_lower(suite) ->
  473:     [];
  474: to_upper_to_lower(doc) ->
  475:     [];
  476: to_upper_to_lower(Config) when is_list(Config) ->
  477:     ?line "1234ABCDEFÅÄÖ=" = string:to_upper("1234abcdefåäö="),
  478:     ?line "éèíúùòóåäöabc()" = string:to_lower("ÉÈÍÚÙÒÓÅÄÖabc()"),
  479:     ?line All = lists:seq(0, 255),
  480: 
  481:     ?line UC = string:to_upper(All),
  482:     ?line 256 = length(UC),
  483:     ?line all_upper_latin1(UC, 0),
  484: 
  485:     ?line LC = string:to_lower(All),
  486:     ?line all_lower_latin1(LC, 0),
  487: 
  488:     ?line LC = string:to_lower(string:to_upper(LC)),
  489:     ?line LC = string:to_lower(string:to_upper(UC)),
  490:     ?line UC = string:to_upper(string:to_lower(LC)),
  491:     ?line UC = string:to_upper(string:to_lower(UC)),
  492:     ok.
  493: 
  494: all_upper_latin1([C|T], C) when 0 =< C, C < $a;
  495: 				$z < C, C < 16#E0;
  496: 				C =:= 16#F7; C =:= 16#FF ->
  497:     all_upper_latin1(T, C+1);
  498: all_upper_latin1([H|T], C) when $a =< C, C =< $z;
  499: 				16#E0 =< C, C =< 16#F6;
  500: 				16#F8 =< C, C =< 16#FE ->
  501:     H = C - 32,
  502:     all_upper_latin1(T, C+1);
  503: all_upper_latin1([], 256) -> ok.
  504: 
  505: all_lower_latin1([C|T], C) when 0 =< C, C < $A;
  506: 				$Z < C, C < 16#C0;
  507: 				C =:= 16#D7;
  508: 				16#DF =< C, C =< 255 ->
  509:     all_lower_latin1(T, C+1);
  510: all_lower_latin1([H|T], C) when $A =< C, C =< $Z;
  511: 				16#C0 =< C, C =< 16#F6;
  512: 				16#C8 =< C, C =< 16#DE ->
  513:     io:format("~p\n", [{H,C}]),
  514:     H = C + 32,
  515:     all_lower_latin1(T, C+1);
  516: all_lower_latin1([], 256) -> ok.
  517: 
  518: join(suite) ->
  519:     [];
  520: join(doc) ->
  521:     [];
  522: join(Config) when is_list(Config) ->
  523:     ?line "erlang rules" = string:join(["erlang", "rules"], " "),
  524:     ?line "a,-,b,-,c" = string:join(["a", "b", "c"], ",-,"),
  525:     ?line "1234" = string:join(["1", "2", "3", "4"], ""),
  526:     ?line [] = string:join([], ""), % OTP-7231
  527:     %% invalid arg type
  528:     ?line {'EXIT',_} = (catch string:join([apa], "")),
  529:     ok.