tcstringlist.pp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. unit tcstringlist;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, fpcunit, testutils, testregistry;
  6. type
  7. { TTestTStringList }
  8. TTestTStringList= class(TTestCase)
  9. private
  10. procedure AddB;
  11. procedure DeleteNegativeIndex;
  12. procedure DeleteTooBigIndex;
  13. procedure ExchangeNegativeIndex1;
  14. procedure ExchangeTooBigIndex1;
  15. procedure ExchangeNegativeIndex2;
  16. procedure ExchangeTooBigIndex2;
  17. procedure AccessNegativeIndex;
  18. procedure AccessTooBigIndex;
  19. Procedure Shuffle;
  20. protected
  21. List : TStringList;
  22. Procedure FillList(ACount : Integer);
  23. procedure SetUp; override;
  24. procedure TearDown; override;
  25. published
  26. procedure TestCreate;
  27. procedure TestAdd;
  28. procedure TestAddIndex;
  29. procedure TestAdd2;
  30. procedure TestInsertFirst;
  31. Procedure TestInsertMiddle;
  32. procedure TestDelete;
  33. Procedure TestClear;
  34. Procedure TestIndexOf;
  35. procedure TestExchange;
  36. procedure TestAccesIndexOutOfBounds;
  37. procedure TestDeleteIndexOutOfBounds;
  38. procedure TestExchangeIndexOutOfBounds;
  39. Procedure TestSort;
  40. Procedure TestSorted;
  41. Procedure TestSortedAdd;
  42. Procedure TestSortedAddAll;
  43. Procedure TestSortedDupError;
  44. procedure TestSortedAddDuplicate;
  45. Procedure TestSortedIndexOf;
  46. Procedure TestChange;
  47. procedure TestChangeAgain;
  48. procedure TestChangeCount;
  49. procedure TestChangeClear;
  50. Procedure TestSetText;
  51. procedure TestSetTextEOL;
  52. procedure TestSetTextEmpty;
  53. procedure TestSetTextEOLEmpty;
  54. end;
  55. { TEventSink }
  56. TEventSink = Class(TObject)
  57. private
  58. FCOunt: Integer;
  59. FSender: TObject;
  60. public
  61. Procedure Change(Sender : TObject);
  62. Procedure Reset;
  63. Property ChangeCount : Integer Read FCOunt;
  64. Property LastSender : TObject Read FSender;
  65. end;
  66. implementation
  67. procedure TTestTStringList.TestCreate;
  68. begin
  69. AssertEquals('Empty list has count 0',0,List.Count);
  70. AssertEquals('Empty list has sorted false',False,List.Sorted);
  71. If List.Duplicates<>dupIgnore then
  72. Fail('Empty list has duplicates=dupIgnore');
  73. end;
  74. procedure TTestTStringList.TestAdd;
  75. begin
  76. FillList(1);
  77. AssertEquals('Add 1 element, count is 1',1,List.Count);
  78. AssertEquals('Add 1 element, last element is "Item 1"','Item 1',List[0]);
  79. end;
  80. procedure TTestTStringList.TestAddIndex;
  81. begin
  82. AssertEquals('Add first element at index 0',0,List.Add('First'));
  83. AssertEquals('Add second element, at index 1',1,List.Add('second'));
  84. end;
  85. procedure TTestTStringList.TestAdd2;
  86. begin
  87. FillList(2);
  88. AssertEquals('Add 2 elements, count is 2',2,List.Count);
  89. AssertEquals('Add 2 elements, first element is "Item 1"','Item 1',List[0]);
  90. AssertEquals('Add 2 elements, second element is "Item 2"','Item 2',List[1]);
  91. end;
  92. procedure TTestTStringList.TestInsertFirst;
  93. begin
  94. FillList(3);
  95. List.Insert(0,'New');
  96. AssertEquals('Insert 1 in 3, count is 4',4,List.Count);
  97. AssertEquals('Insert 1 in 3, first is inserted','New',List[0]);
  98. AssertEquals('Insert 1 in 3, second is old first','Item 1',List[1]);
  99. end;
  100. procedure TTestTStringList.TestInsertMiddle;
  101. begin
  102. FillList(3);
  103. List.Insert(1,'New');
  104. AssertEquals('Insert 1 in 3, count is 4',4,List.Count);
  105. AssertEquals('Insert 1 in 3, 1 is inserted','New',List[1]);
  106. AssertEquals('Insert 1 in 3, 2 is old 2','Item 2',List[2]);
  107. AssertEquals('Insert 1 in 3, 0 is untouched','Item 1',List[0]);
  108. end;
  109. procedure TTestTStringList.TestClear;
  110. begin
  111. FillList(3);
  112. List.Clear;
  113. AssertEquals('Clear: count is 0',0,List.Count);
  114. end;
  115. procedure TTestTStringList.TestIndexOf;
  116. begin
  117. FillList(11);
  118. AssertEquals('Find third element',2,List.IndexOf('Item 3'));
  119. AssertEquals('Find third element, wrong case',2,List.IndexOf('ITEM 3'));
  120. end;
  121. procedure TTestTStringList.TestDelete;
  122. begin
  123. FillList(3);
  124. List.Delete(1);
  125. AssertEquals('Delete 1 from 3, count is 2',2,List.Count);
  126. AssertEquals('Delete 1 from 3, first is "Item 1"','Item 1',List[0]);
  127. AssertEquals('Delete 1 from 3, second is "Item 3"','Item 3',List[1]);
  128. end;
  129. procedure TTestTStringList.TestExchange;
  130. begin
  131. FillList(3);
  132. List.Exchange(0,2);
  133. AssertEquals('Exchange 0 and 2, count is 3',3,List.Count);
  134. AssertEquals('Exchange 0 and 2, first is "Item 3"','Item 3',List[0]);
  135. AssertEquals('Exchange 0 and 2, second is "Item 2"','Item 2',List[1]);
  136. AssertEquals('Exchange 0 and 2, third is "Item 1"','Item 1',List[2]);
  137. end;
  138. procedure TTestTStringList.DeleteNegativeIndex;
  139. begin
  140. List.Delete(-1);
  141. end;
  142. procedure TTestTStringList.DeleteTooBigIndex;
  143. begin
  144. List.Delete(3);
  145. end;
  146. procedure TTestTStringList.ExchangeNegativeIndex1;
  147. begin
  148. List.Exchange(-1,2);
  149. end;
  150. procedure TTestTStringList.ExchangeTooBigIndex1;
  151. begin
  152. List.Exchange(3,2);
  153. end;
  154. procedure TTestTStringList.ExchangeNegativeIndex2;
  155. begin
  156. List.Exchange(2,-1);
  157. end;
  158. procedure TTestTStringList.ExchangeTooBigIndex2;
  159. begin
  160. List.Exchange(2,3);
  161. end;
  162. procedure TTestTStringList.AccessNegativeIndex;
  163. begin
  164. List[-1];
  165. end;
  166. procedure TTestTStringList.AccessTooBigIndex;
  167. begin
  168. List[3];
  169. end;
  170. procedure TTestTStringList.Shuffle;
  171. Var
  172. I,I1,I2 : Integer;
  173. begin
  174. For I:=1 to List.Count* 2 do
  175. begin
  176. I1:=Random(List.Count);
  177. I2:=Random(List.Count);
  178. if I1<>I2 then
  179. List.Exchange(I1,I2);
  180. end;
  181. end;
  182. procedure TTestTStringList.TestAccesIndexOutOfBounds;
  183. begin
  184. FillList(3);
  185. AssertException('Access Negative Index',EStringListError,@AccessNegativeIndex);
  186. AssertException('Access Index too big',EStringListError,@AccessTooBigIndex);
  187. end;
  188. procedure TTestTStringList.TestDeleteIndexOutOfBounds;
  189. begin
  190. FillList(3);
  191. AssertException('Delete Negative Index',EStringListError,@DeleteNegativeIndex);
  192. AssertException('Delete Index too big',EStringListError,@DeleteTooBigIndex);
  193. end;
  194. procedure TTestTStringList.TestExchangeIndexOutOfBounds;
  195. begin
  196. FillList(3);
  197. AssertException('Exchange Negative first index',EStringListError,@ExchangeNegativeIndex1);
  198. AssertException('Exchange Negative second index',EStringListError,@ExchangeNegativeIndex2);
  199. AssertException('Exchange first Index too big',EStringListError,@ExchangeTooBigIndex1);
  200. AssertException('Exchange second Index too big',EStringListError,@ExchangeTooBigIndex2);
  201. end;
  202. procedure TTestTStringList.TestSort;
  203. Var
  204. I : Integer;
  205. begin
  206. FillList(9);
  207. Shuffle;
  208. List.Sort;
  209. For I:=0 to List.Count-1 do
  210. If (List[i]<>'Item '+IntToStr(I+1)) then
  211. Fail(Format('Item at position %d is out of place (%s)',[I,List[i]]));
  212. end;
  213. procedure TTestTStringList.TestSorted;
  214. Var
  215. I : Integer;
  216. begin
  217. FillList(9);
  218. Shuffle;
  219. List.Sorted:=True;
  220. For I:=0 to List.Count-1 do
  221. If (List[i]<>'Item '+IntToStr(I+1)) then
  222. Fail(Format('Item at position %d is out of place (%s)',[I,List[i]]));
  223. end;
  224. procedure TTestTStringList.TestSortedAdd;
  225. begin
  226. List.Sorted:=True;
  227. List.Add('B');
  228. AssertEquals('Add second element at first location in sorted list',0,List.Add('A'));
  229. AssertEquals('Add third element at first location in sorted list',1,List.Add('AB'));
  230. AssertEquals('Add fourth element at last location in sorted list',3,List.Add('C'));
  231. end;
  232. procedure TTestTStringList.TestSortedAddAll;
  233. Var
  234. I : Integer;
  235. begin
  236. List.Sorted:=True;
  237. FillList(9);
  238. For I:=0 to List.Count-1 do
  239. If (List[i]<>'Item '+IntToStr(I+1)) then
  240. Fail(Format('Item at position %d is out of place (%s)',[I,List[i]]));
  241. end;
  242. procedure TTestTStringList.AddB;
  243. begin
  244. List.Add('B');
  245. end;
  246. procedure TTestTStringList.TestSortedDupError;
  247. begin
  248. List.Sorted:=True;
  249. List.Duplicates:=dupError;
  250. List.Add('B');
  251. AssertEquals('Add second element at first location in sorted list',0,List.Add('A'));
  252. AssertException(EStringListError,@AddB);
  253. end;
  254. procedure TTestTStringList.TestSortedAddDuplicate;
  255. begin
  256. List.Sorted:=True;
  257. List.Duplicates:=dupAccept;
  258. List.Add('B');
  259. AssertEquals('Add second element at first location in sorted list',0,List.Add('A'));
  260. AssertEquals('Add third element at first location in sorted list',1,List.Add('B'));
  261. AssertEquals('Add fourth element at last location in sorted list',3,List.Add('C'));
  262. end;
  263. procedure TTestTStringList.TestSortedIndexOf;
  264. // Tests find, as find is called in case of sorted index
  265. begin
  266. List.Sorted:=True;
  267. FillList(11);
  268. // 1 10 11 2 3 - so index 4
  269. AssertEquals('Find third element',4,List.IndexOf('Item 3'));
  270. AssertEquals('Find third element, wrong case',4,List.IndexOf('ITEM 3'));
  271. end;
  272. procedure TTestTStringList.TestChange;
  273. Var
  274. S : TEventSink;
  275. begin
  276. S:=TEventSink.Create;
  277. try
  278. List.OnChange:[email protected];
  279. List.Add('new');
  280. AssertEquals('Change count equals 1 after add',1,S.ChangeCount);
  281. If List<>S.LastSender then
  282. Fail('Sender is list');
  283. finally
  284. S.Free;
  285. end;
  286. end;
  287. procedure TTestTStringList.TestChangeAgain;
  288. Var
  289. S : TEventSink;
  290. begin
  291. S:=TEventSink.Create;
  292. try
  293. List.BeginUpdate;
  294. Try
  295. List.OnChange:[email protected];
  296. List.Add('new');
  297. AssertEquals('Change count equals 0 after add (beginupdate)',0,S.ChangeCount);
  298. If (Nil<>S.LastSender) then
  299. Fail('Sender is nil');
  300. Finally
  301. List.EndUpdate;
  302. end;
  303. AssertEquals('Change count equals 1 after add endupdate',1,S.ChangeCount);
  304. If List<>S.LastSender then
  305. Fail('Sender is list');
  306. finally
  307. S.Free;
  308. end;
  309. end;
  310. procedure TTestTStringList.TestChangeCount;
  311. Var
  312. S : TEventSink;
  313. begin
  314. S:=TEventSink.Create;
  315. try
  316. List.BeginUpdate;
  317. Try
  318. // Count is 1, no notification
  319. List.OnChange:[email protected];
  320. List.Add('new');
  321. AssertEquals('Change count equals 0 after add (1st beginupdate)',0,S.ChangeCount);
  322. If (Nil<>S.LastSender) then
  323. Fail('Sender is nil');
  324. List.BeginUpdate;
  325. Try
  326. List.Add('new2');
  327. // Count is 2, no notification
  328. AssertEquals('Change count equals 0 after add (2nd beginupdate)',0,S.ChangeCount);
  329. If (Nil<>S.LastSender) then
  330. Fail('Sender is nil');
  331. Finally
  332. List.EndUpdate;
  333. end;
  334. // Count is 1 again, no notification
  335. AssertEquals('Change count equals 0 after first endupdate',0,S.ChangeCount);
  336. If (Nil<>S.LastSender) then
  337. Fail('Sender is nil after first endupdate');
  338. Finally
  339. List.EndUpdate;
  340. end;
  341. AssertEquals('Change count equals 1 after add endupdate',1,S.ChangeCount);
  342. If List<>S.LastSender then
  343. Fail('Sender is list');
  344. finally
  345. S.Free;
  346. end;
  347. end;
  348. procedure TTestTStringList.TestChangeClear;
  349. Var
  350. S : TEventSink;
  351. begin
  352. FillList(9);
  353. S:=TEventSink.Create;
  354. try
  355. List.OnChange:[email protected];
  356. List.Clear;
  357. AssertEquals('Change count equals 1 after clear',1,S.ChangeCount);
  358. finally
  359. S.Free;
  360. end;
  361. end;
  362. procedure TTestTStringList.TestSetText;
  363. Const
  364. Lines = 'Line 1'+sLineBreak+'Line 2'+sLineBreak+'Line 3';
  365. begin
  366. List.Text:=Lines;
  367. AssertEquals('3 lines set',3,List.Count);
  368. AssertEquals('First line is "Line 1"','Line 1',List[0]);
  369. AssertEquals('Second line is "Line 2"','Line 2',List[1]);
  370. AssertEquals('Third line is "Line 3"','Line 3',List[2]);
  371. end;
  372. procedure TTestTStringList.TestSetTextEOL;
  373. Const
  374. Lines = 'Line 1'+sLineBreak+'Line 2'+sLineBreak;
  375. begin
  376. List.Text:=Lines;
  377. AssertEquals('2 lines set',2,List.Count);
  378. AssertEquals('First line is "Line 1"','Line 1',List[0]);
  379. AssertEquals('Second line is "Line 2"','Line 2',List[1]);
  380. end;
  381. procedure TTestTStringList.TestSetTextEOLEmpty;
  382. Const
  383. Lines = 'Line 1'+sLineBreak+'Line 2'+sLineBreak+slineBreak;
  384. begin
  385. List.Text:=Lines;
  386. AssertEquals('3 lines set',3,List.Count);
  387. AssertEquals('First line is "Line 1"','Line 1',List[0]);
  388. AssertEquals('Second line is "Line 2"','Line 2',List[1]);
  389. AssertEquals('Third line is empty','',List[2]);
  390. end;
  391. procedure TTestTStringList.TestSetTextEmpty;
  392. Const
  393. Lines = 'Line 1'+sLineBreak+sLineBreak+SlineBreak+'Line 2';
  394. begin
  395. List.Text:=Lines;
  396. AssertEquals('4 lines set',4,List.Count);
  397. AssertEquals('First line is "Line 1"','Line 1',List[0]);
  398. AssertEquals('Second line is empty','',List[1]);
  399. AssertEquals('Third line is empty','',List[2]);
  400. AssertEquals('Fourth line is "Line 2"','Line 2',List[3]);
  401. end;
  402. procedure TTestTStringList.FillList(ACount: Integer);
  403. Var
  404. I : integer;
  405. begin
  406. For I:=1 to ACount do
  407. List.Add('Item '+IntToStr(I));
  408. end;
  409. procedure TTestTStringList.SetUp;
  410. begin
  411. List:=TStringList.Create;
  412. end;
  413. procedure TTestTStringList.TearDown;
  414. begin
  415. FreeAndNil(List);
  416. end;
  417. { TEventSink }
  418. procedure TEventSink.Change(Sender: TObject);
  419. begin
  420. Inc(FCount);
  421. FSender:=Sender;
  422. end;
  423. procedure TEventSink.Reset;
  424. begin
  425. FCount:=0;
  426. FSender:=Nil;
  427. end;
  428. initialization
  429. RegisterTest(TTestTStringList);
  430. end.