tests.generics.stdcollections.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921
  1. {
  2. This file is part of the Free Pascal/NewPascal run time library.
  3. Copyright (c) 2018 by Maciej Izak (hnb),
  4. member of the NewPascal development team (http://newpascal.org)
  5. Copyright(c) 2004-2018 DaThoX
  6. It contains tests for the Free Pascal generics library
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. Acknowledgment
  13. Thanks to Sphere 10 Software (http://sphere10.com) for sponsoring
  14. many new types, tests and major refactoring of entire library
  15. Thanks to Castle Game Engine (https://castle-engine.sourceforge.io)
  16. Part of tests for this module was copied from Castle Game Engine tests
  17. **********************************************************************}
  18. unit tests.generics.stdcollections;
  19. {$mode delphi}
  20. interface
  21. uses
  22. fpcunit, testutils, testregistry, tests.generics.utils,
  23. Classes, SysUtils, Generics.Collections, Generics.Defaults;
  24. type
  25. TTestStdCollections = class(TTestCollections)
  26. private
  27. procedure Test_TList_Notification(AList: TList<string>); overload;
  28. published
  29. // Tests from Castle Game Engine
  30. procedure Test_List;
  31. procedure Test_FreeingManually;
  32. procedure Test_AddingLists;
  33. procedure Test_Sort;
  34. procedure Test_Pack;
  35. procedure Test_RecordsList;
  36. procedure Test_VectorsList;
  37. procedure Test_MethodsList;
  38. // My (c) tests
  39. procedure Test_SortedList;
  40. procedure Test_Queue;
  41. procedure Test_GenericListBox;
  42. procedure Test_TList_Notification; overload;
  43. procedure Test_TSortedList_Notification;
  44. procedure Test_TQueue_Notification;
  45. procedure Test_TStack_Notification;
  46. procedure Test_TObjectList_Notification;
  47. procedure Test_TObjectQueue_Notification;
  48. procedure Test_TObjectStack_Notification;
  49. procedure Test_TrimExcess;
  50. end;
  51. TGenericListBox<T> = class
  52. private class var
  53. F : TList<TComponentClass>;
  54. class procedure Test(ATest: TTestCase);
  55. end;
  56. implementation
  57. class procedure TGenericListBox<T>.Test(ATest: TTestCase);
  58. begin
  59. F := TList<TComponentClass>.Create;
  60. F.Add(TDataModule);
  61. F.Add(nil);
  62. with TList<TComponentClass>.Create(F) do
  63. begin
  64. ATest.AssertTrue(Count = 2);
  65. ATest.AssertTrue(F[0] = Items[0]);
  66. ATest.AssertTrue(F[1] = Items[1]);
  67. ATest.AssertTrue(F[0] = TDataModule);
  68. ATest.AssertTrue(F[1] = nil);
  69. Free;
  70. end;
  71. F.Free;
  72. end;
  73. type
  74. TApple = class
  75. Name: string;
  76. end;
  77. type
  78. TAppleList = class(TObjectList<TApple>)
  79. procedure Pack;
  80. end;
  81. procedure TAppleList.Pack;
  82. begin
  83. while Remove(nil) <> -1 do ;
  84. end;
  85. procedure TTestStdCollections.Test_List;
  86. var
  87. A: TApple;
  88. Apples: TAppleList;
  89. begin
  90. Apples := TAppleList.Create(true);
  91. try
  92. A := TApple.Create;
  93. Apples.Add(A);
  94. Apples.Add(TApple.Create);
  95. A := TApple.Create;
  96. Apples.Add(A);
  97. AssertEquals(3, Apples.Count);
  98. AssertEquals(2, Apples.IndexOf(A));
  99. Apples.Delete(0);
  100. AssertEquals(2, Apples.Count);
  101. AssertEquals(1, Apples.IndexOf(A));
  102. Apples.Remove(A);
  103. AssertEquals(1, Apples.Count);
  104. Apples.Delete(0);
  105. AssertEquals(0, Apples.Count);
  106. finally FreeAndNil(Apples) end;
  107. end;
  108. procedure TTestStdCollections.Test_FreeingManually;
  109. var
  110. A: TApple;
  111. Apples: TAppleList;
  112. begin
  113. Apples := TAppleList.Create(false);
  114. try
  115. A := TApple.Create;
  116. Apples.Add(A);
  117. Apples.Add(A);
  118. Apples.Add(TApple.Create);
  119. { This freeing would be invalid on a list that owns children,
  120. as we free something twice, and we leave some invalid references
  121. (to already freed items) in the list at various stages.
  122. But it should be OK with list that has OwnsChildren = false. }
  123. Apples[0].Free;
  124. Apples[0] := nil;
  125. Apples[1] := nil;
  126. Apples[2].Free;
  127. finally FreeAndNil(Apples) end;
  128. end;
  129. procedure TTestStdCollections.Test_AddingLists;
  130. var
  131. A: TApple;
  132. Apples, Apples2: TAppleList;
  133. begin
  134. Apples := TAppleList.Create(true);
  135. try
  136. A := TApple.Create;
  137. A.Name := 'One';
  138. Apples.Add(A);
  139. A := TApple.Create;
  140. A.Name := 'Two';
  141. Apples.Add(A);
  142. Apples2 := TAppleList.Create(false);
  143. try
  144. Apples2.AddRange(Apples);
  145. Apples2.AddRange(Apples);
  146. Apples2.AddRange(Apples);
  147. AssertEquals(6, Apples2.Count);
  148. AssertEquals('One', Apples2[0].Name);
  149. AssertEquals('Two', Apples2[1].Name);
  150. AssertEquals('One', Apples2[2].Name);
  151. AssertEquals('Two', Apples2[3].Name);
  152. AssertEquals('One', Apples2[4].Name);
  153. AssertEquals('Two', Apples2[5].Name);
  154. finally FreeAndNil(Apples2) end;
  155. finally FreeAndNil(Apples) end;
  156. end;
  157. function CompareApples(constref Left, Right: TApple): Integer;
  158. begin
  159. Result := AnsiCompareStr(Left.Name, Right.Name);
  160. end;
  161. procedure TTestStdCollections.Test_Sort;
  162. type
  163. TAppleComparer = TComparer<TApple>;
  164. var
  165. A: TApple;
  166. L: TAppleList;
  167. begin
  168. L := TAppleList.Create(true);
  169. try
  170. A := TApple.Create;
  171. A.Name := '11';
  172. L.Add(A);
  173. A := TApple.Create;
  174. A.Name := '33';
  175. L.Add(A);
  176. A := TApple.Create;
  177. A.Name := '22';
  178. L.Add(A);
  179. L.Sort(TAppleComparer.Construct(@CompareApples));
  180. AssertEquals(3, L.Count);
  181. AssertEquals('11', L[0].Name);
  182. AssertEquals('22', L[1].Name);
  183. AssertEquals('33', L[2].Name);
  184. finally FreeAndNil(L) end;
  185. end;
  186. procedure TTestStdCollections.Test_Pack;
  187. var
  188. A: TApple;
  189. L: TAppleList;
  190. begin
  191. L := TAppleList.Create(true);
  192. try
  193. L.Add(nil);
  194. A := TApple.Create;
  195. A.Name := '11';
  196. L.Add(A);
  197. L.Add(nil);
  198. A := TApple.Create;
  199. A.Name := '33';
  200. L.Add(A);
  201. A := TApple.Create;
  202. A.Name := '22';
  203. L.Add(A);
  204. L.Add(nil);
  205. L.Add(nil);
  206. L.Pack;
  207. AssertEquals(3, L.Count);
  208. AssertEquals('11', L[0].Name);
  209. AssertEquals('33', L[1].Name);
  210. AssertEquals('22', L[2].Name);
  211. finally FreeAndNil(L) end;
  212. end;
  213. procedure TTestStdCollections.Test_RecordsList;
  214. type
  215. TMyRecord = packed record
  216. A, B: Integer;
  217. end;
  218. TMyRecordList = TList<TMyRecord>;
  219. var
  220. List: TMyRecordList;
  221. R1, R2, R: TMyRecord;
  222. begin
  223. List := TMyRecordList.Create;
  224. try
  225. R1.A := 11;
  226. R1.B := 22;
  227. List.Add(R1);
  228. R2.A := 33;
  229. R2.B := 44;
  230. List.Add(R2);
  231. R2.A := 33;
  232. R2.B := 44;
  233. List.Add(R2);
  234. AssertEquals(3, List.Count);
  235. AssertEquals(11, List[0].A);
  236. AssertEquals(22, List[0].B);
  237. AssertEquals(33, List[1].A);
  238. AssertEquals(44, List[1].B);
  239. AssertEquals(33, List[2].A);
  240. AssertEquals(44, List[2].B);
  241. List.Delete(2);
  242. AssertEquals(2, List.Count);
  243. AssertEquals(11, List[0].A);
  244. AssertEquals(22, List[0].B);
  245. AssertEquals(33, List[1].A);
  246. AssertEquals(44, List[1].B);
  247. AssertEquals(0, List.IndexOf(R1));
  248. AssertEquals(1, List.IndexOf(R2));
  249. // change R1 and R2, to make sure it doesn't matter for tests
  250. R1.A := 111111;
  251. R1.B := 222222;
  252. R2.A := 333333;
  253. R2.B := 444444;
  254. AssertEquals(-1, List.IndexOf(R1));
  255. AssertEquals(-1, List.IndexOf(R2));
  256. R.A := 11;
  257. R.B := 22;
  258. AssertEquals(0, List.IndexOf(R));
  259. R.A := 33;
  260. R.B := 44;
  261. AssertEquals(1, List.IndexOf(R));
  262. R.A := 11;
  263. R.B := 22;
  264. List.Remove(R);
  265. AssertEquals(1, List.Count);
  266. AssertEquals(33, List[0].A);
  267. AssertEquals(44, List[0].B);
  268. R.A := 666;
  269. R.B := 22;
  270. List.Remove(R); // does nothing, no such record
  271. AssertEquals(1, List.Count);
  272. AssertEquals(33, List[0].A);
  273. AssertEquals(44, List[0].B);
  274. finally FreeAndNil(List) end;
  275. end;
  276. procedure TTestStdCollections.Test_VectorsList;
  277. type
  278. TMyVector = packed array [0..1] of Single;
  279. TMyVectorList = TList<TMyVector>;
  280. var
  281. List: TMyVectorList;
  282. R1, R2, R: TMyVector;
  283. begin
  284. List := TMyVectorList.Create;
  285. try
  286. R1[0] := 11;
  287. R1[1] := 22;
  288. List.Add(R1);
  289. R2[0] := 33;
  290. R2[1] := 44;
  291. List.Add(R2);
  292. R2[0] := 33;
  293. R2[1] := 44;
  294. List.Add(R2);
  295. AssertEquals(3, List.Count);
  296. AssertEquals(11, List[0][0]);
  297. AssertEquals(22, List[0][1]);
  298. AssertEquals(33, List[1][0]);
  299. AssertEquals(44, List[1][1]);
  300. AssertEquals(33, List[2][0]);
  301. AssertEquals(44, List[2][1]);
  302. List.Delete(2);
  303. AssertEquals(2, List.Count);
  304. AssertEquals(11, List[0][0]);
  305. AssertEquals(22, List[0][1]);
  306. AssertEquals(33, List[1][0]);
  307. AssertEquals(44, List[1][1]);
  308. AssertEquals(0, List.IndexOf(R1));
  309. AssertEquals(1, List.IndexOf(R2));
  310. // change R1 and R2, to make sure it doesn't matter for tests
  311. R1[0] := 111111;
  312. R1[1] := 222222;
  313. R2[0] := 333333;
  314. R2[1] := 444444;
  315. AssertEquals(-1, List.IndexOf(R1));
  316. AssertEquals(-1, List.IndexOf(R2));
  317. R[0] := 11;
  318. R[1] := 22;
  319. AssertEquals(0, List.IndexOf(R));
  320. R[0] := 33;
  321. R[1] := 44;
  322. AssertEquals(1, List.IndexOf(R));
  323. R[0] := 11;
  324. R[1] := 22;
  325. List.Remove(R);
  326. AssertEquals(1, List.Count);
  327. AssertEquals(33, List[0][0]);
  328. AssertEquals(44, List[0][1]);
  329. R[0] := 666;
  330. R[1] := 22;
  331. List.Remove(R); // does nothing, no such item
  332. AssertEquals(1, List.Count);
  333. AssertEquals(33, List[0][0]);
  334. AssertEquals(44, List[0][1]);
  335. finally FreeAndNil(List) end;
  336. end;
  337. type
  338. TSomeClass = class
  339. procedure Foo(A: Integer);
  340. end;
  341. procedure TSomeClass.Foo(A: Integer);
  342. begin
  343. end;
  344. procedure TTestStdCollections.Test_MethodsList;
  345. type
  346. TMyMethod = procedure (A: Integer) of object;
  347. TMyMethodList = TList<TMyMethod>;
  348. procedure AssertMethodsEqual(const M1, M2: TMyMethod);
  349. begin
  350. AssertTrue(TMethod(M1).Code = TMethod(M2).Code);
  351. AssertTrue(TMethod(M1).Data = TMethod(M2).Data);
  352. end;
  353. var
  354. List: TMyMethodList;
  355. C1, C2, C3: TSomeClass;
  356. M: TMyMethod;
  357. begin
  358. C1 := TSomeClass.Create;
  359. C2 := TSomeClass.Create;
  360. C3 := TSomeClass.Create;
  361. List := TMyMethodList.Create;
  362. try
  363. List.Add(C1.Foo);
  364. List.Add(C2.Foo);
  365. List.Add(C2.Foo);
  366. AssertEquals(3, List.Count);
  367. M := C1.Foo;
  368. AssertMethodsEqual(List[0], M);
  369. M := C2.Foo;
  370. AssertMethodsEqual(List[1], M);
  371. AssertMethodsEqual(List[2], M);
  372. List.Delete(2);
  373. AssertEquals(2, List.Count);
  374. M := C1.Foo;
  375. AssertMethodsEqual(List[0], M);
  376. M := C2.Foo;
  377. AssertMethodsEqual(List[1], M);
  378. AssertEquals(0, List.IndexOf(C1.Foo));
  379. AssertEquals(1, List.IndexOf(C2.Foo));
  380. AssertEquals(-1, List.IndexOf(C3.Foo));
  381. List.Remove(C1.Foo);
  382. AssertEquals(1, List.Count);
  383. M := C2.Foo;
  384. AssertMethodsEqual(List[0], M);
  385. List.Remove(C3.Foo); // does nothing, no such item
  386. AssertEquals(1, List.Count);
  387. M := C2.Foo;
  388. AssertMethodsEqual(List[0], M);
  389. finally FreeAndNil(List) end;
  390. C1.Free;
  391. C2.Free;
  392. C3.Free;
  393. end;
  394. procedure TTestStdCollections.Test_SortedList;
  395. var
  396. LSortedList: TSortedList<Integer>;
  397. i: integer;
  398. LRandomOrder: TArray<Integer>;
  399. begin
  400. LRandomOrder := TArray<Integer>.Create(
  401. 10, 8, 17, 19, 2, 0, 13, 15, 5, 7, 12, 14, 4, 6, 11, 9, 16, 18, 3, 1);
  402. LSortedList := TSortedList<Integer>.Create;
  403. for i in LRandomOrder do
  404. LSortedList.Add(i);
  405. AssertEquals('Wrong Count value for TSortedList', Length(LRandomOrder), LSortedList.Count);
  406. for i := 0 to 19 do
  407. AssertEquals(Format('Wrong item (%d) index (%d) in TSortedList',[LSortedList[i], i]), i, LSortedList[i]);
  408. LSortedList.Free;
  409. end;
  410. procedure TTestStdCollections.Test_Queue;
  411. const
  412. NUMBERS: array[0..2] of Integer = (3,4,5);
  413. var
  414. LQueue: TQueue<Integer>;
  415. i: Integer;
  416. j: Integer;
  417. pi: Pinteger;
  418. begin
  419. LQueue := TQueue<Integer>.Create;
  420. for i := 1 to 5 do
  421. begin
  422. LQueue.Enqueue(i);
  423. AssertEquals(LQueue.Peek, 1);
  424. end;
  425. AssertEquals(LQueue.Dequeue, 1);
  426. AssertEquals(LQueue.Extract, 2);
  427. j := 0;
  428. for i in LQueue do
  429. begin
  430. AssertEquals(i, NUMBERS[j]);
  431. Inc(j);
  432. end;
  433. j := 0;
  434. for pi in LQueue.Ptr^ do
  435. begin
  436. AssertEquals(pi^, NUMBERS[j]);
  437. Inc(j);
  438. end;
  439. LQueue.Free;
  440. end;
  441. procedure TTestStdCollections.Test_TList_Notification(AList: TList<string>);
  442. var
  443. LStringsObj: TEnumerable<string>;
  444. LStringsIntf: IEnumerable<string>;
  445. begin
  446. try
  447. LStringsObj := EnumerableStringsObj(['Ddd', 'Eee']);
  448. LStringsIntf := EnumerableStringsIntf(['Fff', 'Ggg']);
  449. AList.OnNotify := NotifyTestStr;
  450. { Add + AddRange }
  451. NotificationAdd(AList, ['Aaa', 'Bbb', 'Ccc', 'Ddd', 'Eee', 'Fff', 'Ggg'], cnAdded);
  452. AList.Add('Aaa');
  453. AList.AddRange(['Bbb', 'Ccc']);
  454. AList.AddRange(LStringsObj);
  455. AList.AddRange(LStringsIntf);
  456. AssertNotificationsExecutedStr;
  457. { Clear }
  458. NotificationAdd(AList, ['Aaa', 'Bbb', 'Ccc', 'Ddd', 'Eee', 'Fff', 'Ggg'], cnRemoved);
  459. AList.Clear;
  460. AssertNotificationsExecutedStr;
  461. { Insert + InsertRange }
  462. NotificationAdd(AList, ['Aaa', 'Bbb', 'Ccc', 'Ddd', 'Eee', 'Fff', 'Ggg'], cnAdded);
  463. AList.Insert(0, 'Aaa');
  464. AList.InsertRange(1, ['Bbb', 'Ccc']);
  465. AList.InsertRange(3, LStringsObj);
  466. AList.InsertRange(5, LStringsIntf);
  467. AssertNotificationsExecutedStr;
  468. { Remove + Delete + DeleteRange }
  469. NotificationAdd(AList, ['Aaa', 'Bbb', 'Ccc', 'Ddd', 'Eee', 'Fff', 'Ggg'], cnRemoved);
  470. AList.Remove('Aaa');
  471. AList.Delete(0);
  472. AList.DeleteRange(0, 5);
  473. AssertEquals(AList.Count, 0);
  474. AssertNotificationsExecutedStr;
  475. { ExtractIndex, Extract }
  476. NotificationAdd(AList, ['Aaa', 'Bbb', 'Ccc'], cnAdded);
  477. AList.AddRange(['Aaa', 'Bbb', 'Ccc']);
  478. AssertNotificationsExecutedStr;
  479. NotificationAdd(AList, ['Aaa', 'Bbb'], cnExtracted);
  480. AssertEquals(AList.ExtractIndex(0), 'Aaa');
  481. AssertEquals(AList.Extract('Bbb'), 'Bbb');
  482. AssertNotificationsExecutedStr;
  483. { SetItem }
  484. NotificationAdd(AList, 'Ccc', cnRemoved);
  485. NotificationAdd(AList, 'FPC', cnAdded);
  486. AList[0] := 'FPC';
  487. AssertNotificationsExecutedStr;
  488. finally
  489. LStringsObj.Free;
  490. { Free }
  491. NotificationAdd(AList, 'FPC', cnRemoved);
  492. AList.Free;
  493. AssertNotificationsExecutedStr;
  494. end;
  495. end;
  496. procedure TTestStdCollections.Test_TList_Notification;
  497. begin
  498. Test_TList_Notification(TList<string>.Create);
  499. end;
  500. procedure TTestStdCollections.Test_TSortedList_Notification;
  501. var
  502. LList: TSortedList<string>;
  503. begin
  504. LList := TSortedList<string>.Create;
  505. LList.SortStyle := cssUser;
  506. Test_TList_Notification(LList);
  507. end;
  508. procedure TTestStdCollections.Test_TQueue_Notification;
  509. var
  510. LQueue: TQueue<string>;
  511. begin
  512. LQueue := TQueue<string>.Create();
  513. try
  514. LQueue.OnNotify := NotifyTestStr;
  515. { Enqueue }
  516. NotificationAdd(LQueue, ['Aaa', 'Bbb', 'Ccc', 'Ddd'], cnAdded);
  517. LQueue.Enqueue('Aaa');
  518. LQueue.Enqueue('Bbb');
  519. LQueue.Enqueue('Ccc');
  520. LQueue.Enqueue('Ddd');
  521. AssertNotificationsExecutedStr;
  522. { Dequeue }
  523. NotificationAdd(LQueue, 'Aaa', cnRemoved);
  524. AssertEquals(LQueue.Dequeue, 'Aaa');
  525. AssertNotificationsExecutedStr;
  526. { Extract }
  527. NotificationAdd(LQueue, 'Bbb', cnExtracted);
  528. AssertEquals(LQueue.Extract, 'Bbb');
  529. AssertNotificationsExecutedStr;
  530. { Clear }
  531. NotificationAdd(LQueue, ['Ccc', 'Ddd'], cnRemoved);
  532. LQueue.Clear;
  533. AssertNotificationsExecutedStr;
  534. { Enqueue }
  535. NotificationAdd(LQueue, ['FPC', 'Polandball'], cnAdded);
  536. LQueue.Enqueue('FPC');
  537. LQueue.Enqueue('Polandball');
  538. AssertNotificationsExecutedStr;
  539. finally
  540. NotificationAdd(LQueue, ['FPC', 'Polandball'], cnRemoved);
  541. LQueue.Free;
  542. AssertNotificationsExecutedStr;
  543. end;
  544. end;
  545. procedure TTestStdCollections.Test_TStack_Notification;
  546. var
  547. LStack: TStack<string>;
  548. begin
  549. LStack := TStack<string>.Create();
  550. try
  551. LStack.OnNotify := NotifyTestStr;
  552. { Push }
  553. NotificationAdd(LStack, ['Aaa', 'Bbb', 'Ccc', 'Ddd'], cnAdded);
  554. LStack.Push('Aaa');
  555. LStack.Push('Bbb');
  556. LStack.Push('Ccc');
  557. LStack.Push('Ddd');
  558. AssertNotificationsExecutedStr;
  559. { Pop }
  560. NotificationAdd(LStack, 'Ddd', cnRemoved);
  561. AssertEquals(LStack.Pop, 'Ddd');
  562. AssertNotificationsExecutedStr;
  563. { Extract }
  564. NotificationAdd(LStack, 'Ccc', cnExtracted);
  565. AssertEquals(LStack.Extract, 'Ccc');
  566. AssertNotificationsExecutedStr;
  567. { Clear }
  568. NotificationAdd(LStack, ['Bbb', 'Aaa'], cnRemoved);
  569. LStack.Clear;
  570. AssertNotificationsExecutedStr;
  571. { Push }
  572. NotificationAdd(LStack, ['FPC', 'Polandball'], cnAdded);
  573. LStack.Push('FPC');
  574. LStack.Push('Polandball');
  575. AssertNotificationsExecutedStr;
  576. finally
  577. NotificationAdd(LStack, ['Polandball', 'FPC'], cnRemoved);
  578. LStack.Free;
  579. AssertNotificationsExecutedStr;
  580. end;
  581. end;
  582. procedure TTestStdCollections.Test_TObjectList_Notification;
  583. var
  584. LObj: TEnumerable<TObject>;
  585. LIntf: IEnumerable<TObject>;
  586. O: TArray<TObject>;
  587. LList: TObjectList<TObject>;
  588. i: Integer;
  589. begin
  590. try
  591. CreateObjects(O, 8);
  592. LList := TObjectList<TObject>.Create(false);
  593. LList.OnNotify := NotifyTestObj;
  594. LObj := EnumerableObjectsObj([O[3], O[4]]);
  595. LIntf := EnumerableObjectsIntf([O[5], O[6]]);
  596. { Add + AddRange }
  597. NotificationAdd(LList, [O[0], O[1], O[2], O[3], O[4], O[5], O[6]], cnAdded);
  598. LList.Add(O[0]);
  599. LList.AddRange([O[1], O[2]]);
  600. LList.AddRange(LObj);
  601. LList.AddRange(LIntf);
  602. AssertNotificationsExecutedObj;
  603. { Clear }
  604. NotificationAdd(LList, [O[0], O[1], O[2], O[3], O[4], O[5], O[6]], cnRemoved);
  605. LList.Clear;
  606. AssertNotificationsExecutedObj;
  607. { Insert + InsertRange }
  608. NotificationAdd(LList, [O[0], O[1], O[2], O[3], O[4], O[5], O[6]], cnAdded);
  609. LList.Insert(0, O[0]);
  610. LList.InsertRange(1, [O[1], O[2]]);
  611. LList.InsertRange(3, LObj);
  612. LList.InsertRange(5, LIntf);
  613. AssertNotificationsExecutedObj;
  614. { Remove + Delete + DeleteRange }
  615. NotificationAdd(LList, [O[0], O[1], O[2], O[3], O[4], O[5], O[6]], cnRemoved);
  616. LList.Remove(O[0]);
  617. LList.Delete(0);
  618. LList.DeleteRange(0, 5);
  619. AssertEquals(LList.Count, 0);
  620. AssertNotificationsExecutedObj;
  621. { ExtractIndex, Extract }
  622. NotificationAdd(LList, [O[0], O[1], O[2]], cnAdded);
  623. LList.AddRange([O[0], O[1], O[2]]);
  624. AssertNotificationsExecutedObj;
  625. NotificationAdd(LList, [O[0], O[1]], cnExtracted);
  626. AssertTrue(LList.ExtractIndex(0) = O[0]);
  627. AssertTrue(LList.Extract(O[1]) = O[1]);
  628. AssertNotificationsExecutedObj;
  629. { SetItem }
  630. NotificationAdd(LList, O[2], cnRemoved);
  631. NotificationAdd(LList, O[7], cnAdded);
  632. LList[0] := O[7];
  633. AssertNotificationsExecutedObj;
  634. finally
  635. LObj.Free;
  636. { Free }
  637. NotificationAdd(LList, O[7], cnRemoved);
  638. FreeObjects(O);
  639. LList.Free;
  640. AssertNotificationsExecutedObj;
  641. end;
  642. end;
  643. procedure TTestStdCollections.Test_TObjectQueue_Notification;
  644. var
  645. LQueue: TObjectQueue<TObject>;
  646. O: TArray<TObject>;
  647. begin
  648. LQueue := TObjectQueue<TObject>.Create(false);
  649. try
  650. CreateObjects(O, 6);
  651. LQueue.OnNotify := NotifyTestObj;
  652. { Enqueue }
  653. NotificationAdd(LQueue, [O[0], O[1], O[2], O[3]], cnAdded);
  654. LQueue.Enqueue(O[0]);
  655. LQueue.Enqueue(O[1]);
  656. LQueue.Enqueue(O[2]);
  657. LQueue.Enqueue(O[3]);
  658. AssertNotificationsExecutedObj;
  659. { Dequeue }
  660. NotificationAdd(LQueue, O[0], cnRemoved);
  661. LQueue.Dequeue;
  662. AssertNotificationsExecutedObj;
  663. { Extract }
  664. NotificationAdd(LQueue, O[1], cnExtracted);
  665. AssertTrue(LQueue.Extract = O[1]);
  666. AssertNotificationsExecutedObj;
  667. { Clear }
  668. NotificationAdd(LQueue, [O[2], O[3]], cnRemoved);
  669. LQueue.Clear;
  670. AssertNotificationsExecutedObj;
  671. { Enqueue }
  672. NotificationAdd(LQueue, [O[4], O[5]], cnAdded);
  673. LQueue.Enqueue(O[4]);
  674. LQueue.Enqueue(O[5]);
  675. AssertNotificationsExecutedObj;
  676. finally
  677. NotificationAdd(LQueue, [O[4], O[5]], cnRemoved);
  678. FreeObjects(O);
  679. LQueue.Free;
  680. AssertNotificationsExecutedObj;
  681. end;
  682. end;
  683. procedure TTestStdCollections.Test_TObjectStack_Notification;
  684. var
  685. LStack: TStack<TObject>;
  686. O: TArray<TObject>;
  687. begin
  688. LStack := TObjectStack<TObject>.Create(false);
  689. try
  690. CreateObjects(O, 6);
  691. LStack.OnNotify := NotifyTestObj;
  692. { Push }
  693. NotificationAdd(LStack, [O[0], O[1], O[2], O[3]], cnAdded);
  694. LStack.Push(O[0]);
  695. LStack.Push(O[1]);
  696. LStack.Push(O[2]);
  697. LStack.Push(O[3]);
  698. AssertNotificationsExecutedObj;
  699. { Pop }
  700. NotificationAdd(LStack, O[3], cnRemoved);
  701. AssertTrue(LStack.Pop = O[3]);
  702. AssertNotificationsExecutedObj;
  703. { Extract }
  704. NotificationAdd(LStack, O[2], cnExtracted);
  705. AssertTrue(LStack.Extract = O[2]);
  706. AssertNotificationsExecutedObj;
  707. { Clear }
  708. NotificationAdd(LStack, [O[1], O[0]], cnRemoved);
  709. LStack.Clear;
  710. AssertNotificationsExecutedObj;
  711. { Pop }
  712. NotificationAdd(LStack, [O[4], O[5]], cnAdded);
  713. LStack.Push(O[4]);
  714. LStack.Push(O[5]);
  715. AssertNotificationsExecutedObj;
  716. finally
  717. NotificationAdd(LStack, [O[5], O[4]], cnRemoved);
  718. FreeObjects(O);
  719. LStack.Free;
  720. AssertNotificationsExecutedObj;
  721. end;
  722. end;
  723. procedure TTestStdCollections.Test_GenericListBox;
  724. begin
  725. TGenericListBox<Integer>.Test(Self);
  726. end;
  727. procedure TTestStdCollections.Test_TrimExcess;
  728. var
  729. LList: TList<Integer>;
  730. LQueue: TQueue<Integer>;
  731. LStack: TStack<Integer>;
  732. begin
  733. LList := TList<Integer>.Create;
  734. LQueue := TQueue<Integer>.Create;
  735. LStack := TStack<Integer>.Create;
  736. try
  737. LList.AddRange([1, 2, 3, 4, 5, 6]);
  738. LList.DeleteRange(2, 3);
  739. CheckNotEquals(LList.Capacity, LList.Count);
  740. LList.TrimExcess;
  741. AssertEquals(LList.Capacity, LList.Count);
  742. LQueue.Enqueue(1);
  743. LQueue.Enqueue(2);
  744. LQueue.Dequeue;
  745. CheckNotEquals(LQueue.Capacity, LQueue.Count);
  746. LQueue.TrimExcess;
  747. AssertEquals(LQueue.Capacity, LQueue.Count);
  748. LStack.Push(1);
  749. LStack.Push(2);
  750. LStack.Pop;
  751. CheckNotEquals(LStack.Capacity, LStack.Count);
  752. LStack.TrimExcess;
  753. AssertEquals(LStack.Capacity, LStack.Count);
  754. finally
  755. LStack.Free;
  756. LQueue.Free;
  757. LList.Free;
  758. end;
  759. end;
  760. begin
  761. RegisterTest(TTestStdCollections);
  762. end.