2
0

utstringhelp.pp 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264
  1. unit utstringhelp;
  2. {$mode objfpc}{$H+}
  3. //{$modeswitch advancedrecords}
  4. //{$modeswitch typehelpers}
  5. interface
  6. uses
  7. Classes, SysUtils;
  8. implementation
  9. uses punit, utrtl;
  10. Const
  11. TBI = 'To be implemented';
  12. Function TestCompare : String;
  13. Var
  14. r : Integer;
  15. begin
  16. Result:='';
  17. // Simple cases
  18. R:=AnsiString.Compare('A','B');
  19. if not AssertTrue('1. Simple Compare strings (A,B) :'+IntToStr(R)+'<0',R<0) then exit;
  20. R:=AnsiString.Compare('B','A');
  21. if not AssertTrue('2. Simple Compare strings (B,A) :'+IntToStr(R)+'>0',R>0) then exit;
  22. R:=AnsiString.Compare('A','A');
  23. if not AssertTrue('3. Simple Compare strings (A,A) :'+IntToStr(R)+'=0',R=0) then exit;
  24. R:=AnsiString.Compare('A','a', true);
  25. if not AssertTrue('4. Simple ignore case Compare strings (A,a) : '+IntToStr(R)+'=0',R=0) then exit;
  26. R:=AnsiString.Compare('b','a',True);
  27. if not AssertTrue('5. Simple ignore case Compare strings (b,a) : '+IntToStr(R)+'>0',R>0) then exit;
  28. R:=AnsiString.Compare('A','a',[coIgnoreCase]);
  29. if not AssertTrue('6. [coIgnoreCase] Compare strings (A,a) : '+IntToStr(R)+'=0',R=0) then exit;
  30. R:=AnsiString.Compare('b','a',[coIgnoreCase]);
  31. if not AssertTrue('7. [coIgnoreCase] Compare strings (b,a) : '+IntToStr(R)+'>0',R>0) then exit;
  32. // Check whether index is observed.
  33. R:=AnsiString.Compare('AA',1,'AB',1,1);
  34. if not AssertTrue('8. Compare(''AA'',1,''AB'',1,1) :'+IntToStr(R)+'<0',R<0) then exit;
  35. R:=AnsiString.Compare('AB',1,'AA',1,1);
  36. if not AssertTrue('9. Compare(''AB'',1,''AA'',1,1) :'+IntToStr(R)+'>0',R>0) then exit;
  37. R:=AnsiString.Compare('AA',1,'AA',1,1);
  38. if not AssertTrue('10. Compare(''AA'',1,''AA'',1,1) :'+IntToStr(R)+'=0',R=0) then exit;
  39. // Make sure only len chars are used.
  40. R:=AnsiString.Compare('AAC',1,'ABD',1,1);
  41. if not AssertTrue('11. Compare(''AAC'',1,''ABD'',1,1) :'+IntToStr(R)+'<0',R<0) then exit;
  42. R:=AnsiString.Compare('ABC',1,'AAD',1,1);
  43. if not AssertTrue('12 Compare(''ABC'',1,''AAD'',1,1) :'+IntToStr(R)+'>0',R>0) then exit;
  44. R:=AnsiString.Compare('AAC',1,'AAD',1,1);
  45. if not AssertTrue('13. Compare(''AAC'',1,''AAD'',1,1) :'+IntToStr(R)+'=0',R=0) then exit;
  46. // Index, case insensitive
  47. R:=AnsiString.Compare('AA',1,'Aa',1,1,true);
  48. if not AssertTrue('14. Compare(''AA'',1,''Aa'',1,1,true) : '+IntToStr(R)+'=0',R=0) then exit;
  49. R:=AnsiString.Compare('Ab',1,'Aa',1,1,True);
  50. if not AssertTrue('15. Compare(''Ab'',1,''Aa'',1,1,True) : '+IntToStr(R)+'>0',R>0) then exit;
  51. R:=AnsiString.Compare('A',1,'a',1,1,[coIgnoreCase]);
  52. if not AssertTrue('16. Compare(''A'',1,''a'',1,1,[coIgnoreCase]) : '+IntToStr(R)+'=0',R=0) then exit;
  53. // Index, maxlen, case insensitive
  54. R:=AnsiString.Compare('AAC',1,'AaD',1,1,true);
  55. if not AssertTrue('17. Compare(''AAC'',1,''AaD'',1,1,true) : '+IntToStr(R)+'=0',R=0) then exit;
  56. R:=AnsiString.Compare('AbC',1,'AaD',1,1,True);
  57. if not AssertTrue('18. Compare(''AbC'',1,''AaD'',1,1,True) : '+IntToStr(R)+'>0',R>0) then exit;
  58. R:=AnsiString.Compare('AAC',1,'AaD',1,1,[coIgnoreCase]);
  59. if not AssertTrue('19. Compare(''AAC'',1,''AaD'',1,1,[coIgnoreCase]) : '+IntToStr(R)+'=0',R=0) then exit;
  60. end;
  61. Function TestCompareOrdinal : String;
  62. Var
  63. r : Integer;
  64. begin
  65. Result:='';
  66. // Simple
  67. R:=AnsiString.CompareOrdinal('A','B');
  68. if not AssertTrue('1. Simple Compare strings (A,B) :'+IntToStr(R)+'<0',R<0) then exit;
  69. R:=AnsiString.CompareOrdinal('B','A');
  70. if not AssertTrue('2. Simple Compare strings (B,A) :'+IntToStr(R)+'>0',R>0) then exit;
  71. R:=AnsiString.CompareOrdinal('A','A');
  72. if not AssertTrue('3. Simple Compare strings (A,A) :'+IntToStr(R)+'=0',R=0) then exit;
  73. // Index
  74. R:=AnsiString.CompareOrdinal('AA',1,'AB',1,1);
  75. if not AssertTrue('4. Simple Compare strings (AA,1,AB,1,1) :'+IntToStr(R)+'<0',R<0) then exit;
  76. R:=AnsiString.CompareOrdinal('AB',1,'AA',1,1);
  77. if not AssertTrue('5. Simple Compare strings (AB,1,AA,1,1) :'+IntToStr(R)+'>0',R>0) then exit;
  78. R:=AnsiString.CompareOrdinal('AA',1,'AA',1,1);
  79. if not AssertTrue('6. Simple Compare strings (AA,1,AA,1,1) :'+IntToStr(R)+'=0',R=0) then exit;
  80. // Index, maxlen
  81. R:=AnsiString.CompareOrdinal('AAC',1,'ABD',1,1);
  82. if not AssertTrue('7. Simple Compare strings (AAC,1,ABD,1,1) :'+IntToStr(R)+'<0',R<0) then exit;
  83. R:=AnsiString.CompareOrdinal('ABC',1,'AAD',1,1);
  84. if not AssertTrue('8. Simple Compare strings (ABC,1,AAD,1,1) :'+IntToStr(R)+'>0',R>0) then exit;
  85. R:=AnsiString.CompareOrdinal('AAD',1,'AAD',1,1);
  86. if not AssertTrue('9. Simple Compare strings (AAC,1,AAD,1,1) :'+IntToStr(R)+'=0',R=0) then exit;
  87. end;
  88. Function TestCompareText : String;
  89. Var
  90. r : Integer;
  91. begin
  92. Result:='';
  93. R:=AnsiString.CompareText('A','B');
  94. if not AssertTrue('1. Simple Compare strings (A,B) :'+IntToStr(R)+'<0',R<0) then exit;
  95. R:=AnsiString.CompareText('B','A');
  96. if not AssertTrue('Simple Compare strings (B,A) :'+IntToStr(R)+'>0',R>0) then exit;
  97. R:=AnsiString.CompareText('A','A');
  98. if not AssertTrue('Simple Compare strings (A,A) :'+IntToStr(R)+'=0',R=0) then exit;
  99. //
  100. R:=AnsiString.CompareText('A','b');
  101. if not AssertTrue('Simple Compare strings (A,b) :'+IntToStr(R)+'<0',R<0) then exit;
  102. R:=AnsiString.CompareText('B','a');
  103. if not AssertTrue('Simple Compare strings (B,a) :'+IntToStr(R)+'>0',R>0) then exit;
  104. R:=AnsiString.CompareText('A','a');
  105. if not AssertTrue('Simple Compare strings (A,a) :'+IntToStr(R)+'=0',R=0) then exit;
  106. end;
  107. Function TestCopy : String;
  108. var
  109. A,S : String;
  110. begin
  111. Result:='';
  112. A:=TBI;
  113. S:=AnsiString.Copy(A);
  114. if not AssertEquals('Copy creates equal copy',A,S) then exit;
  115. end;
  116. Function TestCreate : String;
  117. Var
  118. A : String;
  119. begin
  120. Result:='';
  121. A:=AnsiString.Create('*',5);
  122. if not AssertEquals('Create with char and length','*****',A) then exit;
  123. A:=AnsiString.Create(['a','b','c','d','e']);
  124. if not AssertEquals('Create with array of char','abcde',A) then exit;
  125. A:=AnsiString.Create(['a','b','c','d','e'],1,3);
  126. if not AssertEquals('Create with array of char and index, len','bcd',A) then exit;
  127. end;
  128. Function TestEndsText : String;
  129. begin
  130. Result:='';
  131. if not AssertTrue('1. EndsText, correct',AnsiString.EndsText('be','to be or not to be')) then exit;
  132. if not AssertTrue('2. EndsText, correct, case insensitive',AnsiString.EndsText('BE','to be or not to be')) then exit;
  133. if not AssertFalse('3. EndsText, not correct',AnsiString.EndsText('de','to be or not to be')) then exit;
  134. if not AssertFalse('4. EndsText, empty',Ansistring.EndsText('','to be or not to be')) then exit;
  135. end;
  136. Function TestEquals : String;
  137. Var
  138. A,B : String;
  139. begin
  140. Result:='';
  141. A:='Yes';
  142. B:='No';
  143. if not AssertFalse('1. Equals(A,B)',AnsiString.Equals(A,B)) then exit;
  144. B:='Yes';
  145. if not AssertTrue('2. Equals(A,B)',AnsiString.Equals(A,B)) then exit;
  146. B:='No';
  147. if not AssertFalse('3. A.Equals(B)',A.Equals(B)) then exit;
  148. B:='Yes';
  149. if not AssertTrue('4. A.Equals(B)',A.Equals(B)) then exit;
  150. end;
  151. Function TestFormat : String;
  152. begin
  153. Result:='';
  154. if not AssertEquals('1. Format as class function','A1 BC', AnsiString.Format('A%d B%s',[1,'C'])) then exit;
  155. if not AssertEquals('2. Format function','A1 BC', 'A%d B%s'.Format([1,'C'])) then exit;
  156. end;
  157. Function TestIsNullOrEmpty : String;
  158. begin
  159. Result:='';
  160. If Not AssertTrue('1. Empty string returns true',AnsiString.IsNullOrEmpty('')) then exit;
  161. end;
  162. Function IsNullOrWhiteSpace : String;
  163. Var
  164. C : Char;
  165. begin
  166. Result:='';
  167. If Not AssertTrue('2. Empty string returns true',AnsiString.IsNullOrEmpty('')) then exit;
  168. For C:=#1 to #32 do
  169. If Not AssertTrue('Char '+IntToStr(Ord(C))+' string returns true',AnsiString.IsNullOrEmpty(C)) then exit;
  170. end;
  171. Function TestJoin : String;
  172. Var
  173. C : Char;
  174. Cu : Currency;
  175. I6 : Int64;
  176. Q : QWord;
  177. F : Extended;
  178. W : Widestring;
  179. U : UnicodeString;
  180. S : AnsiString;
  181. P : PChar;
  182. PW : PWideChar;
  183. // Variants unit used when enabling this.
  184. // V : Variant;
  185. begin
  186. Result:='';
  187. C:='3';
  188. Cu:=12.3;
  189. I6:=1234;
  190. F:=1234.5;
  191. Q:=123456;
  192. S:='AS';
  193. W:='WS';
  194. U:='US';
  195. P:=PChar(S);
  196. PW:=PWideChar(U);
  197. // V:='Var';
  198. if not AssertEquals('1 element','ABC',AnsiString.Join(' ',['ABC'])) then exit;
  199. if not AssertEquals('2 elements','ABC DEF',AnsiString.Join(' ',['ABC','DEF'])) then exit;
  200. if not AssertEquals('3 elements','ABC DEF GHI',AnsiString.Join(' ',['ABC','DEF','GHI'])) then exit;
  201. if not AssertEquals('5 elements, index','ABC DEF GHI',AnsiString.Join(' ',['NONO','ABC','DEF','GHI','nono'],1,3)) then exit;
  202. { if not AssertEquals('Array of const','ABC 1 True 3 12.3 1234 '+FloatToStr(F)+' 123456 AS US WS AS US Var',
  203. AnsiString.Join(' ',['ABC',1,True,C,CU,I6,F,Q,S,U,W,P,PW,V])) then exit;}
  204. end;
  205. Function TestLowerCase : String;
  206. begin
  207. Result:='';
  208. if not AssertEquals('1. Simple Lowercase','abc',AnsiString.Lowercase('ABC')) then exit;
  209. end;
  210. Function TestParse : String;
  211. Var
  212. E : Extended;
  213. begin
  214. Result:='';
  215. E:=12.3;
  216. if not AssertEquals('Boolean','-1',AnsiString.Parse(True))then exit;
  217. if not AssertEquals('Integer','12',AnsiString.Parse(Integer(12)))then exit;
  218. if not AssertEquals('Int64','45',AnsiString.Parse(Int64(45)))then exit;
  219. if not AssertEquals('Extended',FloatToStr(E),AnsiString.Parse(E)) then exit;
  220. end;
  221. Function TestToBoolean : String;
  222. begin
  223. Result:='';
  224. If not AssertTrue('Class function, true',AnsiString.ToBoolean('True')) then exit;
  225. If not AssertTrue('function 1',AnsiString.ToBoolean('1')) then exit;
  226. If not AssertFalse('Class function false',AnsiString.ToBoolean('False')) then exit;
  227. If not AssertFalse('function 0',AnsiString.ToBoolean('0')) then exit;
  228. end;
  229. Function TestToDouble : String;
  230. begin
  231. Result:='';
  232. If not AssertEquals('Class function, 0',0.0,AnsiString.ToDouble('0.0')) then exit;
  233. If not AssertEquals('Class function, 1.2',1.2,AnsiString.ToDouble('1.2')) then exit;
  234. If not AssertEquals('function, 0',0.0,'0.0'.ToDouble) then exit;
  235. If not AssertEquals('function, 1.2',1.2,'1.2'.ToDouble) then exit;
  236. end;
  237. Function TestToExtended : String;
  238. begin
  239. Result:='';
  240. If not AssertEquals('Class function, 0',0.0,AnsiString.ToExtended('0.0')) then exit;
  241. If not AssertEquals('Class function, 1.2',1.2,AnsiString.ToExtended('1.2')) then exit;
  242. If not AssertEquals('function, 0',0.0,'0.0'.ToExtended) then exit;
  243. If not AssertEquals('function, 1.2',1.2,'1.2'.ToExtended) then exit;
  244. end;
  245. Function TestToInt64 : String;
  246. begin
  247. Result:='';
  248. If not AssertEquals('Class function, 0',0,AnsiString.ToInt64('0')) then exit;
  249. If not AssertEquals('Class function, 12',12,AnsiString.ToInt64('12')) then exit;
  250. If not AssertEquals('Class function, 1234567890123',1234567890123,AnsiString.ToInt64('1234567890123')) then exit;
  251. // 2 characters because it does not work on length 1, compiler assumes Char as in Delphi
  252. If not AssertEquals('Class function, 0',0,'00'.ToInt64) then exit;
  253. If not AssertEquals('Class function, 12',12,'12'.ToInt64) then exit;
  254. If not AssertEquals('Class function, 1234567890123',1234567890123,'1234567890123'.ToInt64) then exit;
  255. end;
  256. Function TestToInteger : String;
  257. begin
  258. Result:='';
  259. If not AssertEquals('Class function, 0',0,AnsiString.ToInteger('0')) then exit;
  260. If not AssertEquals('Class function, 12',12,AnsiString.ToInteger('12')) then exit;
  261. If not AssertEquals('Class function, 123456789',123456789,AnsiString.ToInteger('123456789')) then exit;
  262. // 2 characters because it does not work on length 1, compiler assumes Char as in Delphi
  263. If not AssertEquals('Class function, 0',0,'00'.ToInteger) then exit;
  264. If not AssertEquals('Class function, 12',12,'12'.ToInteger) then exit;
  265. If not AssertEquals('Class function, 123456789',123456789,'123456789'.ToInteger) then exit;
  266. end;
  267. Function TestToSingle : String;
  268. begin
  269. Result:='';
  270. If not AssertEquals('Class function, 0',Single(0.0),AnsiString.ToSingle('0.0')) then exit;
  271. If not AssertEquals('Class function, 1.2',Single(1.2),AnsiString.ToSingle('1.2')) then exit;
  272. If not AssertEquals('function, 0',Single(0.0),'0.0'.ToSingle) then exit;
  273. If not AssertEquals('function, 1.2',Single(1.2),'1.2'.ToSingle) then exit;
  274. end;
  275. Function TestUppercase : String;
  276. begin
  277. Result:='';
  278. if not AssertEquals('1. Simple Lowercase','ABC',AnsiString.UpperCase('abc')) then exit;
  279. end;
  280. Function TestCompareTo : String;
  281. begin
  282. Result:='';
  283. // 2 characters because it does not work on length 1, compiler assumes Char as in Delphi
  284. if not AssertTrue('1. A<B','AA'.CompareTo('AB')<0) then exit;
  285. if not AssertTrue('1. A=A','AA'.CompareTo('AA')=0) then exit;
  286. if not AssertTrue('1. B>A','AB'.CompareTo('AA')>0) then exit;
  287. end;
  288. Function TestContains : String;
  289. begin
  290. Result:='';
  291. if not AssertTrue('ABC contains AB','ABC'.Contains('AB')) then exit;
  292. if not AssertTrue('ABC contains BC','ABC'.Contains('BC')) then exit;
  293. if not AssertTrue('ABC contains B','ABC'.Contains('B')) then exit;
  294. if not AssertFalse('ABC does not contain empty','ABC'.Contains('')) then exit;
  295. if not AssertFalse('ABC does not contain DEF','ABC'.Contains('DEF')) then exit;
  296. if not AssertFalse('ABC does not contain a','ABC'.Contains('a')) then exit;
  297. end;
  298. Function TestCopyTo : String;
  299. Type
  300. TCharArray = Array Of Char;
  301. Const
  302. Res1 : Array[0..4] of Char = ('T','o',' ','b','e');
  303. Var
  304. S : AnsiString;
  305. A : TCharArray;
  306. I : Integer;
  307. begin
  308. Result:='';
  309. A:=Default(TCharArray);
  310. S:=TBI;
  311. SetLength(A,5);
  312. S.CopyTo(0,A,0,5);
  313. For I:=0 to 4 do
  314. if not AssertEquals('Zero indexes, Char '+IntToStr(i),Res1[I],A[I]) then exit;
  315. S:='AB'+S;
  316. S.CopyTo(2,A,0,5);
  317. For I:=0 to 4 do
  318. if not AssertEquals('Source index, zero dest index, Char '+IntToStr(i),Res1[I],A[I]) then exit;
  319. SetLength(A,8);
  320. S.CopyTo(2,A,3,5);
  321. For I:=0 to 4 do
  322. if not AssertEquals('Source index, dest index, Char '+IntToStr(i),Res1[I],A[I+3]) then exit;
  323. end;
  324. Function TestCountChar : String;
  325. begin
  326. Result:='';
  327. if not AssertEquals('Empty string',0,''.CountChar(' ')) then exit;
  328. if not AssertEquals('Start and end ',2,' ** '.CountChar(' ')) then exit;
  329. if not AssertEquals('Middle',2,'* *'.CountChar(' ')) then exit;
  330. end;
  331. Function TestDeQuotedString : String;
  332. Const
  333. C = TBI;
  334. C2 = 'To be ''implemented';
  335. C3 = 'To be "implemented';
  336. Var
  337. S : String;
  338. begin
  339. Result:='';
  340. S:=''''+C+'''';
  341. If Not AssertEquals('Simple case of '+S,C,S.DequotedString) then exit;
  342. S:=''''+StringReplace(C2,'''','''''',[rfReplaceAll])+'''';
  343. If Not AssertEquals('Quoted case of '+S,C2,S.DequotedString) then exit;
  344. S:='"'+C+'"';
  345. If Not AssertEquals('Simple case of '+S,C,S.DequotedString('"')) then exit;
  346. S:='"'+StringReplace(C3,'"','""',[rfReplaceAll])+'"';
  347. If Not AssertEquals('Quoted case of '+S,C3,S.DequotedString('"')) then exit;
  348. end;
  349. Function TestEndsWith : String;
  350. Var
  351. S : AnsiString;
  352. begin
  353. Result:='';
  354. S:=TBI;
  355. If not AssertTrue('length 0', S.EndsWith('')) then exit;
  356. If not AssertTrue('length 1', S.EndsWith('d')) then exit;
  357. If not AssertTrue('length 2', S.EndsWith('ed')) then exit;
  358. If not AssertTrue('equal length (same)', S.EndsWith(S)) then exit;
  359. If not AssertFalse('length+2', S.EndsWith(S+'ed')) then exit;
  360. If not AssertFalse('Random string', S.EndsWith('erd')) then exit;
  361. If not AssertTrue('match case ', S.EndsWith('ed',False)) then exit;
  362. If not AssertFalse('match case, no match ', S.EndsWith('eD',False)) then exit;
  363. If not AssertTrue('no match case, match ', S.EndsWith('ED',True)) then exit;
  364. If not AssertFalse('no match case, no match ', S.EndsWith('DED',True)) then exit;
  365. end;
  366. Function TestGetHashCode : String;
  367. {
  368. Function GetHashCode: Integer;
  369. }
  370. Var
  371. S : AnsiString;
  372. begin
  373. Result:='';
  374. S:=TBI;
  375. if not AssertTrue('Nonzero hashcode',S.GetHashCode<>0) then exit;
  376. // A more meaningful test would be nice...
  377. end;
  378. Function TestIndexOf : String;
  379. Var
  380. S : String;
  381. begin
  382. Result:='';
  383. S:=TBI+' To perfection';
  384. // Char based.
  385. If not AssertEquals('Char, Nonexisting returns -1',-1,S.IndexOf('a')) then exit;
  386. If not AssertEquals('Char, Existing, zero based',0,S.IndexOf('T')) then exit;
  387. If not AssertEquals('Char, Case sensitive',-1,S.IndexOf('I')) then exit;
  388. If not AssertEquals('Char, using start index',10,S.IndexOf('e',5)) then exit;
  389. If not AssertEquals('Char, using start index and count, not found',-1,S.IndexOf('e',5,5)) then exit;
  390. If not AssertEquals('Char, using start index and count,found',10,S.IndexOf('e',5,6)) then exit;
  391. // String based.
  392. If not AssertEquals('String, Nonexisting returns -1',-1,S.IndexOf('a')) then exit;
  393. If not AssertEquals('String, zero based',0,S.IndexOf('T')) then exit;
  394. If not AssertEquals('String, case sensitive',-1,S.IndexOf('I')) then exit;
  395. If not AssertEquals('String, using start index',18,S.IndexOf('To',2)) then exit;
  396. If not AssertEquals('String, using start index and count ',-1,S.IndexOf('To be',2,4)) then exit;
  397. If not AssertEquals('String, using start index and count (partial overlap)',-1,S.IndexOf('To be',16,4)) then exit;
  398. end;
  399. Function TestIndexOfAny : String;
  400. Var
  401. S : String;
  402. ES : Array of Char;
  403. begin
  404. Result:='';
  405. S:=TBI;
  406. es:=[];
  407. // Just a set
  408. SetLength(ES,0);
  409. if not AssertEquals('Empty set',-1,S.IndexOfAny(ES)) then exit;
  410. if not AssertEquals('Single char in set, no match',-1,S.IndexOfAny(['a'])) then exit;
  411. if not AssertEquals('Single char in set, no match (wrong case)',-1,S.IndexOfAny(['O'])) then exit;
  412. if not AssertEquals('2 chars in set, no match',-1,S.IndexOfAny(['a','z'])) then exit;
  413. if not AssertEquals('Single char in set, match',4,S.IndexOfAny(['e'])) then exit;
  414. if not AssertEquals('2 chars in set, 2nd matches',3,S.IndexOfAny(['a','b'])) then exit;
  415. // Start index
  416. if not AssertEquals('StartIndex, Empty set',-1,S.IndexOfAny(ES,2)) then exit;
  417. if not AssertEquals('StartIndex, Single char in set, no match',-1,S.IndexOfAny(['a'],2)) then exit;
  418. if not AssertEquals('StartIndex, Single char in set, no match (wrong case)',-1,S.IndexOfAny(['O'],1)) then exit;
  419. if not AssertEquals('StartIndex, Single char in set, no match (index too big)',-1,S.IndexOfAny(['o'],2)) then exit;
  420. if not AssertEquals('StartIndex, 2 chars in set, no match',-1,S.IndexOfAny(['a','z'],4)) then exit;
  421. if not AssertEquals('StartIndex, Single char in set, match',4,S.IndexOfAny(['e'],3)) then exit;
  422. if not AssertEquals('StartIndex, 2 chars in set, 2nd matches',3,S.IndexOfAny(['a','b'],2)) then exit;
  423. // Start index, count
  424. if not AssertEquals('StartIndex, count, Empty set',-1,S.IndexOfAny(ES,2,3)) then exit;
  425. if not AssertEquals('StartIndex, count, Single char in set, no match',-1,S.IndexOfAny(['a'],2)) then exit;
  426. if not AssertEquals('StartIndex, count, Single char in set, no match (wrong case)',-1,S.IndexOfAny(['O'],1)) then exit;
  427. if not AssertEquals('StartIndex, count, Single char in set, no match (index too big)',-1,S.IndexOfAny(['o'],2,4)) then exit;
  428. if not AssertEquals('StartIndex, count, Single char in set, no match (index too big, count too small)',-1,S.IndexOfAny(['o'],5,5)) then exit;
  429. if not AssertEquals('StartIndex, count, 2 chars in set, no match',-1,S.IndexOfAny(['a','z'],4,3)) then exit;
  430. if not AssertEquals('StartIndex, count, Single char in set, match',4,S.IndexOfAny(['e'],3,4)) then exit;
  431. if not AssertEquals('StartIndex, count, Single char in set, match in range',10,S.IndexOfAny(['e'],5,6)) then exit;
  432. if not AssertEquals('StartIndex, count, 2 chars in set, 2nd matches',3,S.IndexOfAny(['a','b'],2,3)) then exit;
  433. end;
  434. Function TestIndexOfAnyString : String;
  435. Var
  436. S : String;
  437. ES : Array of String;
  438. begin
  439. Result:='';
  440. S:=TBI;
  441. ES:=[];
  442. // Just a set
  443. SetLength(ES,0);
  444. if not AssertEquals('Empty set',-1,S.IndexOfAny(ES)) then exit;
  445. if not AssertEquals('Single string in set, no match',-1,S.IndexOfAny(['ab'])) then exit;
  446. if not AssertEquals('Single string in set, no match (wrong case)',-1,S.IndexOfAny(['TO'])) then exit;
  447. if not AssertEquals('2 strings in set, no match',-1,S.IndexOfAny(['ab','yz'])) then exit;
  448. if not AssertEquals('Single string in set, match',4,S.IndexOfAny(['e '])) then exit;
  449. if not AssertEquals('2 strings in set, 2nd matches',3,S.IndexOfAny(['ee','be'])) then exit;
  450. // Start index
  451. if not AssertEquals('StartIndex, Empty set',-1,S.IndexOfAny(ES,2)) then exit;
  452. if not AssertEquals('StartIndex, Single string in set, no match',-1,S.IndexOfAny(['aa'],2)) then exit;
  453. if not AssertEquals('StartIndex, Single string in set, no match (wrong case)',-1,S.IndexOfAny(['TO'],1)) then exit;
  454. if not AssertEquals('StartIndex, Single string in set, no match (index too big)',-1,S.IndexOfAny(['To'],2)) then exit;
  455. if not AssertEquals('StartIndex, 2 strings in set, no match',-1,S.IndexOfAny(['aa','zz'],4)) then exit;
  456. if not AssertEquals('StartIndex, Single string in set, match',4,S.IndexOfAny(['e '],3)) then exit;
  457. if not AssertEquals('StartIndex, 2 strings in set, 2nd matches',3,S.IndexOfAny(['aa','be'],2)) then exit;
  458. // Start index, count
  459. if not AssertEquals('StartIndex, count, Empty set',-1,S.IndexOfAny(ES,2,3)) then exit;
  460. if not AssertEquals('StartIndex, count, Single string in set, no match',-1,S.IndexOfAny(['aa'],2)) then exit;
  461. if not AssertEquals('StartIndex, count, Single string in set, no match (wrong case)',-1,S.IndexOfAny(['tO'],1)) then exit;
  462. if not AssertEquals('StartIndex, count, Single string in set, no match (index too big)',-1,S.IndexOfAny(['To'],2,4)) then exit;
  463. if not AssertEquals('StartIndex, count, Single string in set, no match (index too big, count too small)',-1,S.IndexOfAny(['To'],5,5)) then exit;
  464. if not AssertEquals('StartIndex, count, 2 strings in set, no match',-1,S.IndexOfAny(['aa','zz'],4,3)) then exit;
  465. if not AssertEquals('StartIndex, count, Single string in set, match',4,S.IndexOfAny(['e '],3,4)) then exit;
  466. if not AssertEquals('StartIndex, count, Single string in set, match in range',10,S.IndexOfAny(['em'],5,7)) then exit;
  467. if not AssertEquals('StartIndex, count, 2 strings in set, 2nd matches',3,S.IndexOfAny(['aa','be'],2,3)) then exit;
  468. end;
  469. Function TestIndexOfUnquoted : String;
  470. Var
  471. S : String;
  472. begin
  473. // Tests created from special cases in Embarcadero docs.
  474. Result:='';
  475. S:='"Thias" ias iat';
  476. If not AssertEquals('Simple case, match',8,S.IndexOfUnquoted('ia','"','"')) then exit;
  477. S:='"This is" it';
  478. If not AssertEquals('Simple case, match',10,S.IndexOfUnquoted(' ','"','"')) then exit;
  479. S:='"Thias ias iat';
  480. If not AssertEquals('Opening but not closed',-1,S.IndexOfAnyUnquoted('ia','"','"')) then exit;
  481. S:='"Thias" "ias" "iat"';
  482. If not AssertEquals('Only spaces unquoted',-1,S.IndexOfAnyUnquoted('ia','"','"')) then exit;
  483. S:='<Thias <ias>> iat';
  484. If not AssertEquals('Different start/end quotes',14,S.IndexOfAnyUnquoted('ia','<','>')) then exit;
  485. S:='"Thias" ias iat';
  486. If not AssertEquals('Start index',3,S.IndexOfAnyUnquoted('ia','"','"',1)) then exit;
  487. S:='Thias" "ias" "iat';
  488. If not AssertEquals('Start index',-1,S.IndexOfAnyUnquoted('ia','"','"',6)) then exit;
  489. end;
  490. Function TestIndexOfAnyUnquoted : String;
  491. Var
  492. S : String;
  493. begin
  494. // Tests created from special cases in Embarcadero docs.
  495. Result:='';
  496. S:='"This" is it';
  497. If not AssertEquals('Simple case, match',7,S.IndexOfAnyUnquoted(['i'],'"','"')) then exit;
  498. If not AssertEquals('Simple case 2, match',7,S.IndexOfAnyUnquoted(['a','i'],'"','"')) then exit;
  499. S:='"This is it';
  500. If not AssertEquals('Opening but not closed',-1,S.IndexOfAnyUnquoted(['i'],'"','"')) then exit;
  501. S:='"This" "is" "it"';
  502. If not AssertEquals('Only spaces unquoted',-1,S.IndexOfAnyUnquoted(['i'],'"','"')) then exit;
  503. S:='<This <is>> it';
  504. If not AssertEquals('Different start/end quotes',12,S.IndexOfAnyUnquoted(['i'],'<','>')) then exit;
  505. S:='"This" is it';
  506. // The documentation is WRONG on this one. Delphi prints 3, not 2 as in the docs.
  507. If not AssertEquals('Start index',3,S.IndexOfAnyUnquoted(['i'],'"','"',1)) then exit;
  508. S:='This" "is" "it';
  509. If not AssertEquals('Start index',-1,S.IndexOfAnyUnquoted(['i'],'"','"',5)) then exit;
  510. end;
  511. Function TestInsert : String;
  512. Var
  513. S : String;
  514. begin
  515. Result:='';
  516. S:=TBI;
  517. If not AssertEquals('0 based (1) (result)','All To be implemented',S.Insert(0,'All ')) then exit;
  518. If not AssertEquals('0 based (1) (self)','All To be implemented',S) then exit;
  519. S:=TBI;
  520. If not AssertEquals('0 based (2)','To be completely implemented',S.Insert(6,'completely ')) then exit;
  521. S:=TBI;
  522. If not AssertEquals('Negative index','completely '+TBI,S.Insert(-3,'completely ')) then exit;
  523. S:=TBI;
  524. If not AssertEquals('Too big index',TBI+'completely ',S.Insert(Length(S)+1,'completely ')) then exit;
  525. end;
  526. Function TestIsDelimiter : String;
  527. Var
  528. S : String;
  529. begin
  530. Result:='';
  531. S:=TBI;
  532. if not AssertTrue('Simple case, true',S.IsDelimiter('be',3)) then exit;
  533. if not AssertFalse('Simple case, false',S.IsDelimiter('ba',4)) then exit;
  534. end;
  535. Function TestIsEmpty : String;
  536. Var
  537. S : String;
  538. begin
  539. Result:='';
  540. S:='';
  541. if not AssertTrue('Simple case, true',S.IsEmpty) then exit;
  542. S:='abc';
  543. if not AssertFalse('Simple case, false',S.IsEmpty) then exit;
  544. end;
  545. Function TestLastDelimiter : String;
  546. Var
  547. S : String;
  548. begin
  549. Result:='';
  550. S:=TBI;
  551. if not AssertEquals('Simple case, match, zero based ',0,S.LastDelimiter('T')) then exit;
  552. if not AssertEquals('Simple case, no match ',-1,S.LastDelimiter('a')) then exit;
  553. if not AssertEquals('Simple case',3,S.LastDelimiter('b')) then exit;
  554. if not AssertEquals('Simple, check last match ',Length(TBI)-2,S.LastDelimiter('e')) then exit;
  555. if not AssertEquals('Multi, no match ',-1,S.LastDelimiter('qy')) then exit;
  556. if not AssertEquals('Multi, last match 1',Length(TBI)-1,S.LastDelimiter('ed')) then exit;
  557. if not AssertEquals('Multi, last match 2',Length(TBI)-2,S.LastDelimiter('eb')) then exit;
  558. end;
  559. Function TestLastIndexOf : String;
  560. Var
  561. S : String;
  562. begin
  563. Result:='';
  564. S:=TBI;
  565. if not AssertEquals('Simple case, no match',-1,S.LastIndexOf('a')) then exit;
  566. if not AssertEquals('Simple case, zero based',0,S.LastIndexOf('T')) then exit;
  567. if not AssertEquals('Simple case last',Length(TBI)-2,S.LastIndexOf('e')) then exit;
  568. if not AssertEquals('Simple case, startindex too low',-1,S.LastIndexOf('e',3)) then exit;
  569. if not AssertEquals('Simple case, startindex OK ',4,S.LastIndexOf('e',7)) then exit;
  570. if not AssertEquals('Simple case, startindex OK, count too small ',-1,S.LastIndexOf('e',7,3)) then exit;
  571. if not AssertEquals('Simple case, startindex OK, count border',4,S.LastIndexOf('e',7,4)) then exit;
  572. end;
  573. Function TestLastIndexOfString : String;
  574. Var
  575. S : String;
  576. begin
  577. Result:='';
  578. S:=TBI;
  579. if not AssertEquals('Simple case, no match',-1,S.LastIndexOf('aa')) then exit;
  580. if not AssertEquals('Simple case, zero based',0,S.LastIndexOf('To')) then exit;
  581. if not AssertEquals('Simple case last',Length(TBI)-2,S.LastIndexOf('ed')) then exit;
  582. if not AssertEquals('Simple case, startindex too low',-1,S.LastIndexOf('ed',3)) then exit;
  583. if not AssertEquals('Simple case, startindex OK ',3,S.LastIndexOf('be',7)) then exit;
  584. if not AssertEquals('Simple case, startindex OK, count too small ',-1,S.LastIndexOf('be',7,3)) then exit;
  585. if not AssertEquals('Simple case, startindex OK, count border',3,S.LastIndexOf('be',7,4)) then exit;
  586. end;
  587. Function TestLastIndexOfAny : String;
  588. Var
  589. S : String;
  590. begin
  591. Result:='';
  592. S:=TBI;
  593. if not AssertEquals('Simple case, no match',-1,S.LastIndexOfAny(['x'])) then exit;
  594. if not AssertEquals('Double case, no match',-1,S.LastIndexOfAny(['a','x'])) then exit;
  595. if not AssertEquals('Simple case, zero based',0,S.LastIndexOfAny(['T'])) then exit;
  596. if not AssertEquals('Double case, zero based',0,S.LastIndexOfAny(['T','q'])) then exit;
  597. if not AssertEquals('Simple case last',Length(TBI)-2,S.LastIndexOf('e')) then exit;
  598. if not AssertEquals('Simple case, startindex too low',-1,S.LastIndexOf('e',3)) then exit;
  599. if not AssertEquals('Simple case, startindex OK ',4,S.LastIndexOf('e',7)) then exit;
  600. if not AssertEquals('Simple case, startindex OK, count too small ',-1,S.LastIndexOf('e',7,3)) then exit;
  601. if not AssertEquals('Simple case, startindex OK, count border',4,S.LastIndexOf('e',7,4)) then exit;
  602. end;
  603. Function TestPadLeft : String;
  604. Var
  605. S : String;
  606. begin
  607. Result:='';
  608. S:='TBI';
  609. if not AssertEquals('Default char',' TBI',S.PadLeft(5)) then exit;
  610. if not AssertEquals('Length reached','TBI',S.PadLeft(3)) then exit;
  611. if not AssertEquals('Length over','TBI',S.PadLeft(2)) then exit;
  612. if not AssertEquals('Alternate char','**TBI',S.PadLeft(5,'*')) then exit;
  613. end;
  614. Function TestPadRight : String;
  615. Var
  616. S : String;
  617. begin
  618. Result:='';
  619. S:='TBI';
  620. if not AssertEquals('Default char','TBI ',S.PadRight(5)) then exit;
  621. if not AssertEquals('Original remains untouched','TBI',S) then exit;
  622. if not AssertEquals('Length reached','TBI',S.PadRight(3)) then exit;
  623. if not AssertEquals('Original remains untouched','TBI',S) then exit;
  624. if not AssertEquals('Length over','TBI',S.PadRight(2)) then exit;
  625. if not AssertEquals('Original remains untouched','TBI',S) then exit;
  626. if not AssertEquals('Alternate char','TBI**',S.PadRight(5,'*')) then exit;
  627. if not AssertEquals('Original remains untouched','TBI',S) then exit;
  628. end;
  629. Function TestQuotedString : String;
  630. Const
  631. TII = '''This'' is it';
  632. TII2 = '"This" is it';
  633. Var
  634. S : String;
  635. begin
  636. Result:='';
  637. S:=TBI;
  638. if not AssertEquals('Default case',''''+TBI+'''',S.QuotedString) then exit;
  639. if not AssertEquals('Original remains untouched',TBI,S) then exit;
  640. S:=TII;
  641. if not AssertEquals('Quotes present, doubled','''''''This'''' is it''',S.QuotedString) then exit;
  642. if not AssertEquals('Original remains untouched',TII,S) then exit;
  643. // Other quote char
  644. S:=TBI;
  645. if not AssertEquals('Quote ", Default case','"'+TBI+'"',S.QuotedString('"')) then exit;
  646. if not AssertEquals('Quote ", Original remains untouched',TBI,S) then exit;
  647. S:=TII2;
  648. if not AssertEquals('Quote ", Quotes present, doubled','"""This"" is it"',S.QuotedString('"')) then exit;
  649. if not AssertEquals('Quote ", Original remains untouched',TII2,S) then exit;
  650. end;
  651. Function TestRemove : String;
  652. Var
  653. S : String;
  654. begin
  655. Result:='';
  656. S:=TBI;
  657. if not AssertEquals('Delete all','',S.Remove(0)) then exit;
  658. if not AssertEquals('Delete all, original unchanged',TBI,S) then exit;
  659. if not AssertEquals('Delete from index','To',S.Remove(2)) then exit;
  660. if not AssertEquals('Delete all, original unchanged',TBI,S) then exit;
  661. if not AssertEquals('Delete from negative index',TBI,S.Remove(-1)) then exit;
  662. if not AssertEquals('Delete from negative, original unchanged',TBI,S) then exit;
  663. // Count
  664. if not AssertEquals('Delete N from start','be implemented',S.Remove(0,3)) then exit;
  665. if not AssertEquals('Delete all, original unchanged',TBI,S) then exit;
  666. if not AssertEquals('Delete from start index, count','To implemented',S.Remove(2,3)) then exit;
  667. if not AssertEquals('Delete from start index, count, original unchanged',TBI,S) then exit;
  668. if not AssertEquals('Delete from negative index, count',TBI,S.Remove(-1,4)) then exit;
  669. if not AssertEquals('Delete from negative index, count, original unchanged',TBI,S) then exit;
  670. end;
  671. Function TestReplace : String;
  672. {
  673. Function Replace(OldChar: Char; NewChar: Char): string; overload;
  674. Function Replace(OldChar: Char; NewChar: Char; ReplaceFlags: TReplaceFlags): string; overload;
  675. Function Replace(const OldValue: string; const NewValue: string): string; overload;
  676. Function Replace(const OldValue: string; const NewValue: string; ReplaceFlags: TReplaceFlags): string; overload;
  677. }
  678. Var
  679. S : String;
  680. begin
  681. Result:='';
  682. S:=TBI;
  683. // Char
  684. if not AssertEquals('Simple char','to be implemented',S.Replace('T','t')) then exit;
  685. if not AssertEquals('Simple char, original unchanged',TBI,S) then exit;
  686. if not AssertEquals('Simple char is case sensitive',TBI,S.Replace('t','t')) then exit;
  687. if not AssertEquals('Simple char is replace all','To ba implamantad',S.Replace('e','a')) then exit;
  688. if not AssertEquals('Simple char, case insensitive','to be implemented',S.Replace('t','t',[rfIgnoreCase])) then exit;
  689. if not AssertEquals('Simple char, only first','To ba implemented',S.Replace('e','a',[])) then exit;
  690. if not AssertEquals('Simple char, replace all','To ba implamantad',S.Replace('e','a',[rfReplaceAll])) then exit;
  691. // String
  692. if not AssertEquals('Simple string','ta be implemented',S.Replace('To','ta')) then exit;
  693. if not AssertEquals('Simple string, case sensitive',TBI,S.Replace('to','ta')) then exit;
  694. S:='AB AB';
  695. if not AssertEquals('Simple string is replace all','cd cd',S.Replace('AB','cd')) then exit;
  696. S:=TBI;
  697. if not AssertEquals('Simple string, case insensitive','to be implemented',S.Replace('to','to',[rfIgnoreCase])) then exit;
  698. S:='AB AB AB';
  699. if not AssertEquals('Simple sting, only first','cd AB AB',S.Replace('AB','cd',[])) then exit;
  700. S:='AB AB AB';
  701. if not AssertEquals('Simple string, replace all','cd cd cd',S.Replace('AB','cd',[rfReplaceAll])) then exit;
  702. end;
  703. Function TestSplit : String;
  704. Function TestArray(Msg : string; Aexpected : Array of string; AActual : TStringArray) : boolean;
  705. Var
  706. I : integer;
  707. begin
  708. Result:=False;
  709. if not AssertEquals(Msg+': Length correct',Length(AExpected),Length(AActual)) then exit;
  710. for I:=0 to Length(AExpected)-1 do
  711. if not AssertEquals(Msg+': Element '+IntToStr(i)+' correct',AExpected[i],AActual[i]) then exit;
  712. Result:=True;
  713. end;
  714. Const
  715. TII = '"This is" it' ;
  716. TII2 = '<This is> it' ;
  717. TII3 = '<This is> it' ;
  718. CA: array[0..7] of string = ('F0;F1;F2', ';F1;F2', ';;F2', 'F0;;F2', ';;', 'F0;F1;', 'F0;;', ';F1;');
  719. Var
  720. S : String;
  721. C: TStringArray;
  722. begin
  723. Result:='';
  724. S:='a b';
  725. C:=S.Split([' ']);
  726. if not TestArray('One letter',['a','b'],C) then exit;
  727. S:=TBI;
  728. C:=S.Split([' ']);
  729. if not TestArray('Simple case',['To','be','implemented'],C) then exit;
  730. C:=S.Split([' '],2);
  731. if not TestArray('Simple case, count',['To','be'],C) then exit;
  732. S:=TII;
  733. C:=S.Split([' ','"']);
  734. if not TestArray('Quote and space',['','This','is','','it'],C) then exit;
  735. C:=S.Split([' ','"'],TStringSplitOptions.ExcludeEmpty);
  736. if not TestArray('Quote and space, exclude empty',['This','is','it'],C) then exit;
  737. C:=S.Split([' '],2);
  738. if not TestArray('Quote and space, count 2',['"This','is"'],C) then exit;
  739. C:=S.Split([' ','"'],2,TStringSplitOptions.ExcludeEmpty);
  740. if not TestArray('Quote and space, exclude empty,count 2',['This','is'],C) then exit;
  741. C:=S.Split([' ','"'],1,TStringSplitOptions.ExcludeEmpty);
  742. if not TestArray('Quote and space, exclude empty, count 1',['This'],C) then exit;
  743. C:=S.Split([' '],'"','"');
  744. if not TestArray('Quoted, space only',['"This is"','it'],C) then exit;
  745. C:=S.Split([' '],'"','"',1);
  746. if not TestArray('Quoted, space only; count',['"This is"'],C) then exit;
  747. S:=TII2;
  748. C:=S.Split([' '],'<','>');
  749. if not TestArray('Quoted <>, space only',['<This is>','it'],C) then exit;
  750. S:=TII3;
  751. C:=S.Split([' '],'<','>');
  752. if not TestArray('Quoted <>, space only, have space',['<This is>','','it'],C) then exit;
  753. S:=TII3;
  754. C:=S.Split([' '],'<','>',TStringSplitOptions.ExcludeEmpty);
  755. if not TestArray('Quoted <>, space only, have space, exclude empty',['<This is>','it'],C) then exit;
  756. for S in CA do
  757. begin
  758. C := S.Split([';']);
  759. if Length(C)<>3 then
  760. exit('Error : expect 3 elements when splitting string '+S);
  761. end;
  762. end;
  763. Function TestSplitString : String;
  764. Function TestArray(Msg : string; Aexpected : Array of string; AActual : TStringArray) : boolean;
  765. Var
  766. I : integer;
  767. begin
  768. Result:=False;
  769. if not AssertEquals(Msg+': Length correct',Length(AExpected),Length(AActual)) then exit;
  770. for I:=0 to Length(AExpected)-1 do
  771. if not AssertEquals(Msg+': Element '+IntToStr(i)+' correct',AExpected[i],AActual[i]) then exit;
  772. Result:=True;
  773. end;
  774. Const
  775. TII = '"This is" it' ;
  776. TII2 = '<This is> it' ;
  777. TII3 = '<This is> it' ;
  778. Var
  779. S : String;
  780. C: TStringArray;
  781. begin
  782. Result:='';
  783. S:=StringReplace(TBI,' ',' ',[rfReplaceAll]);
  784. { C:=S.Split([' ']);
  785. if not TestArray('Simple case',['To','be','implemented'],C) then exit;
  786. C:=S.Split([' '],2);
  787. if not TestArray('Simple case, count',['To','be'],C) then exit;
  788. S:=TII;
  789. C:=S.Split([' ','"']);
  790. if not TestArray('Quote and space',['','This','is','','it'],C) then exit;
  791. C:=S.Split([' ','"'],ExcludeEmpty);
  792. if not TestArray('Quote and space, exclude empty',['This','is','it'],C) then exit;
  793. C:=S.Split([' '],2);
  794. if not TestArray('Quote and space, count 2',['"This','is"'],C) then exit;
  795. C:=S.Split([' ','"'],2,ExcludeEmpty);
  796. if not TestArray('Quote and space, exclude empty,count 2',['This','is'],C) then exit;
  797. C:=S.Split([' ','"'],1,ExcludeEmpty);
  798. if not TestArray('Quote and space, exclude empty, count 1',['This'],C) then exit;
  799. }
  800. S:=TII;
  801. C:=S.Split([' '],'"','"');
  802. if not TestArray('Quoted, space only',['"This is"','it'],C) then exit;
  803. C:=S.Split([' '],'"','"',1);
  804. if not TestArray('Quoted, space only; count',['"This is"'],C) then exit;
  805. S:=TII2;
  806. C:=S.Split([' '],'<','>');
  807. if not TestArray('Quoted <>, space only',['<This is>','it'],C) then exit;
  808. S:=TII3;
  809. C:=S.Split([' '],'<','>');
  810. if not TestArray('Quoted <>, space only, have space',['<This is>','','it'],C) then exit;
  811. S:=TII3;
  812. C:=S.Split([' '],'<','>',TStringSplitOptions.ExcludeEmpty);
  813. if not TestArray('Quoted <>, space only, have space, exclude empty',['<This is>','it'],C) then exit;
  814. end;
  815. Function TestStartsWith : String;
  816. Var
  817. S : String;
  818. begin
  819. Result:='';
  820. S:=TBI;
  821. if not AssertTrue('Match empty',S.StartsWith('')) then exit;
  822. if not AssertTrue('Match',S.StartsWith('To')) then exit;
  823. if not AssertFalse('Match, case sensitive',S.StartsWith('to')) then exit;
  824. if not AssertFalse('No Match',S.StartsWith('ab')) then exit;
  825. if not AssertFalse('No Match, complete',S.StartsWith('To n')) then exit;
  826. if not AssertFalse('Match, only start',S.StartsWith('be')) then exit;
  827. if not AssertTrue('Match, case insensitive',S.StartsWith('To')) then exit;
  828. end;
  829. Function TestSubstring : String;
  830. Var
  831. S : String;
  832. begin
  833. Result:='';
  834. S:=TBI;
  835. // No length
  836. if not AssertEquals('0 based','ed',S.SubString(Length(S)-2)) then exit;
  837. if not AssertEquals('0 based, original untouched',TBI,S) then exit;
  838. if not AssertEquals('Index too big','',S.SubString(Length(S)+2)) then exit;
  839. if not AssertEquals('Index negative',TBI,S.SubString(-1)) then exit;
  840. // Length
  841. if not AssertEquals('0 based','To',S.SubString(0,2)) then exit;
  842. if not AssertEquals('0 based, original untouched',TBI,S) then exit;
  843. if not AssertEquals('Index too big','',S.SubString(Length(S)+2,3)) then exit;
  844. if not AssertEquals('Index negative','To',S.SubString(-1,2)) then exit;
  845. if not AssertEquals('Sub, index','be',S.SubString(3,2)) then exit;
  846. end;
  847. Function TestToCharArray : String;
  848. Var
  849. S : String;
  850. C : TCharArray;
  851. I : integer;
  852. begin
  853. Result:='';
  854. S:=TBI;
  855. C:=S.ToCharArray;
  856. if not AssertEquals('No args, length',Length(S),Length(C)) then exit;
  857. For I:=1 to Length(S) do
  858. if not AssertEquals('No args, character (1-based) : '+IntToStr(i),S[i],C[i-1]) then exit;
  859. C:=S.ToCharArray(3,Length(S)-3);
  860. if not AssertEquals('No args, length',Length(S)-3,Length(C)) then exit;
  861. For I:=4 to Length(S) do
  862. if not AssertEquals('Args(3,len), character (1-based) : '+IntToStr(i),S[i],C[i-4]) then exit;
  863. end;
  864. Function TestToLower : String;
  865. Var
  866. S : String;
  867. begin
  868. Result:='';
  869. S:=TBI;
  870. if not AssertEquals('Lowercase','to be implemented',S.ToLower) then exit;
  871. if not AssertEquals('Lowercase, original unmodified',TBI,S) then exit;
  872. end;
  873. Function TestToLowerInvariant : String;
  874. Var
  875. S : String;
  876. begin
  877. Result:='';
  878. S:=TBI;
  879. if not AssertEquals('Lowercase','to be implemented',S.ToLowerInvariant) then exit;
  880. if not AssertEquals('Lowercase, original unmodified',TBI,S) then exit;
  881. // This probably needs testing of some special cases.
  882. end;
  883. Function TestToUpper : String;
  884. Var
  885. S : String;
  886. begin
  887. Result:='';
  888. S:=TBI;
  889. if not AssertEquals('Lowercase','TO BE IMPLEMENTED',S.ToUpper) then exit;
  890. if not AssertEquals('Lowercase, original unmodified',TBI,S) then exit;
  891. end;
  892. Function TestToUpperInvariant : String;
  893. Var
  894. S : String;
  895. begin
  896. Result:='';
  897. S:=TBI;
  898. if not AssertEquals('Lowercase','TO BE IMPLEMENTED',S.ToUpperInvariant) then exit;
  899. if not AssertEquals('Lowercase, original unmodified',TBI,S) then exit;
  900. // This probably needs testing of some special cases.
  901. end;
  902. Function TestTrim : String;
  903. Var
  904. T,S : String;
  905. C : Char;
  906. begin
  907. Result:='';
  908. S:=TBI;
  909. For C:=#0 to #32 do
  910. S:=C+S+C;
  911. T:=S;
  912. if not AssertEquals('By default all chars below #32 stripped',TBI,S.Trim) then exit;
  913. if not AssertEquals('Original unmodified',T,S) then exit;
  914. S:='lmn'+TBI+'lmn';
  915. T:=S;
  916. if not AssertEquals('Strip all indicated chars',TBI,S.Trim(['l','m','n'])) then exit;
  917. if not AssertEquals('Strip all indicated chars, Original unmodified',T,S) then exit;
  918. end;
  919. Function TestTrimLeft : String;
  920. Var
  921. O,T,S : String;
  922. C : Char;
  923. begin
  924. Result:='';
  925. S:=TBI;
  926. T:=TBI;
  927. For C:=#0 to #32 do
  928. begin
  929. S:=C+S+C;
  930. T:=T+C;
  931. end;
  932. O:=S;
  933. if not AssertEquals('By default all chars below #32 stripped',T,S.TrimLeft) then exit;
  934. if not AssertEquals('Original unmodified',O,S) then exit;
  935. S:='lmn'+TBI+'lmn';
  936. T:=TBI+'lmn';
  937. O:=S;
  938. if not AssertEquals('Strip all indicated chars',T,S.TrimLeft(['l','m','n'])) then exit;
  939. if not AssertEquals('Strip all indicated chars, Original unmodified',O,S) then exit;
  940. end;
  941. Function TestTrimRight : String;
  942. Var
  943. O,T,S : String;
  944. C : Char;
  945. begin
  946. Result:='';
  947. S:=TBI;
  948. T:=TBI;
  949. For C:=#0 to #32 do
  950. begin
  951. S:=C+S+C;
  952. T:=C+T;
  953. end;
  954. O:=S;
  955. if not AssertEquals('By default all chars below #32 stripped',T,S.TrimRight) then exit;
  956. if not AssertEquals('Original unmodified',O,S) then exit;
  957. S:='lmn'+TBI+'lmn';
  958. T:='lmn'+TBI;
  959. O:=S;
  960. if not AssertEquals('Strip all indicated chars',T,S.TrimRight(['l','m','n'])) then exit;
  961. if not AssertEquals('Strip all indicated chars, Original unmodified',O,S) then exit;
  962. end;
  963. Function TestTrimEnd : String;
  964. Var
  965. O,T,S : String;
  966. begin
  967. Result:='';
  968. S:='lmn'+TBI+'lmn';
  969. T:='lmn'+TBI;
  970. O:=S;
  971. if not AssertEquals('Strip all indicated chars',T,S.TrimRight(['l','m','n'])) then exit;
  972. if not AssertEquals('Strip all indicated chars, Original unmodified',O,S) then exit;
  973. end;
  974. Function TestTrimStart : String;
  975. Var
  976. O,T,S : String;
  977. begin
  978. Result:='';
  979. S:='lmn'+TBI+'lmn';
  980. T:=TBI+'lmn';
  981. O:=S;
  982. if not AssertEquals('Strip all indicated chars',T,S.TrimLeft(['l','m','n'])) then exit;
  983. if not AssertEquals('Strip all indicated chars, Original unmodified',O,S) then exit;
  984. end;
  985. Function TestChars : String;
  986. Var
  987. S : String;
  988. I : Integer;
  989. begin
  990. Result:='';
  991. S:=TBI;
  992. For I:=1 to Length(S) do
  993. if not AssertEquals('Character (1-based)'+IntToStr(i),S[i],S.Chars[i-1]) then exit;
  994. end;
  995. Function TestLength : String;
  996. Var
  997. S : String;
  998. begin
  999. Result:='';
  1000. S:=TBI;
  1001. if not AssertEquals('Correct length',Length(TBI),S.Length) then exit;
  1002. end;
  1003. (* // Template code;
  1004. Function Test : String;
  1005. begin
  1006. Result:='To be implemented';
  1007. end;
  1008. *)
  1009. Procedure RegisterStringHelperTests;
  1010. Var
  1011. P : PSuite;
  1012. begin
  1013. P:=AddSuite('StringHelper',EnsureSuite('SysUtils'));
  1014. AddTest('TestCompare',@TestCompare,P);
  1015. AddTest('TestCompareOrdinal',@TestCompareOrdinal,P);
  1016. AddTest('TestCompareText',@TestCompareText,P);
  1017. AddTest('TestCopy',@TestCopy,P);
  1018. AddTest('TestCreate',@TestCreate,P);
  1019. AddTest('TestEndsText',@TestEndsText,P);
  1020. AddTest('TestEquals',@TestEquals,P);
  1021. AddTest('TestFormat',@TestFormat,P);
  1022. AddTest('TestIsNullOrEmpty',@TestIsNullOrEmpty,P);
  1023. AddTest('TestJoin',@TestJoin,P);
  1024. AddTest('TestLowerCase',@TestLowerCase,P);
  1025. AddTest('TestParse',@TestParse,P);
  1026. AddTest('TestToBoolean',@TestToBoolean,P);
  1027. AddTest('TestToDouble',@TestToDouble,P);
  1028. AddTest('TestToExtended',@TestToExtended,P);
  1029. AddTest('TestToInt64',@TestToInt64,P);
  1030. AddTest('TestToInteger',@TestToInteger,P);
  1031. AddTest('TestToSingle',@TestToSingle,P);
  1032. AddTest('TestUppercase',@TestUppercase,P);
  1033. AddTest('TestCompareTo',@TestCompareTo,P);
  1034. AddTest('TestCopyTo',@TestCopyTo,P);
  1035. AddTest('TestContains',@TestContains,P);
  1036. AddTest('TestCountChar',@TestCountChar,P);
  1037. AddTest('TestDeQuotedString',@TestDeQuotedString,P);
  1038. AddTest('TestEndsWith',@TestEndsWith,P);
  1039. AddTest('TestGetHashCode',@TestGetHashCode,P);
  1040. AddTest('TestIndexOf',@TestIndexOf,P);
  1041. AddTest('TestIndexOfAny',@TestIndexOfAny,P);
  1042. AddTest('TestIndexOfAnyString',@TestIndexOfAnyString,P);
  1043. AddTest('TestIndexOfUnQuoted',@TestIndexOfUnQuoted,P);
  1044. AddTest('TestIndexOfAnyUnquoted',@TestIndexOfAnyUnquoted,P);
  1045. AddTest('TestInsert',@TestInsert,P);
  1046. AddTest('TestIsDelimiter',@TestIsDelimiter,P);
  1047. AddTest('TestIsEmpty',@TestIsEmpty,P);
  1048. AddTest('TestLastDelimiter',@TestLastDelimiter,P);
  1049. AddTest('TestLastIndexOf',@TestLastIndexOf,P);
  1050. AddTest('TestLastIndexOfString',@TestLastIndexOfString,P);
  1051. AddTest('TestLastIndexOfAny',@TestLastIndexOfAny,P);
  1052. AddTest('TestPadLeft',@TestPadLeft,P);
  1053. AddTest('TestPadRight',@TestPadRight,P);
  1054. AddTest('TestQuotedString',@TestQuotedString,P);
  1055. AddTest('TestRemove',@TestRemove,P);
  1056. AddTest('TestReplace',@TestReplace,P);
  1057. AddTest('TestSplit',@TestSplit,P);
  1058. AddTest('TestSplitString',@TestSplitString,P);
  1059. AddTest('TestStartsWith',@TestStartsWith,P);
  1060. AddTest('TestSubstring',@TestSubstring,P);
  1061. AddTest('TestToCharArray',@TestToCharArray,P);
  1062. AddTest('TestToLower',@TestToLower,P);
  1063. AddTest('TestToLowerInvariant',@TestToLowerInvariant,P);
  1064. AddTest('TestToUpper',@TestToUpper,P);
  1065. AddTest('TestToUpperInvariant',@TestToUpperInvariant,P);
  1066. AddTest('TestTrim',@TestTrim,P);
  1067. AddTest('TestTrimLeft',@TestTrimLeft,P);
  1068. AddTest('TestTrimRight',@TestTrimRight,P);
  1069. AddTest('TestTrimEnd',@TestTrimEnd,P);
  1070. AddTest('TestTrimStart',@TestTrimStart,P);
  1071. AddTest('TestChars',@TestChars,P);
  1072. AddTest('TestLength',@TestLength,P);
  1073. // AddTest('Test',@Test,P);
  1074. end;
  1075. initialization
  1076. RegisterStringHelperTests;
  1077. end.