Test_StringMap.dpr 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. (* _ _
  2. * | |__ _ __ ___ ___ | | __
  3. * | '_ \| '__/ _ \ / _ \| |/ /
  4. * | |_) | | | (_) | (_) | <
  5. * |_.__/|_| \___/ \___/|_|\_\
  6. *
  7. * Microframework which helps to develop web Pascal applications.
  8. *
  9. * Copyright (c) 2012-2021 Silvio Clecio <[email protected]>
  10. *
  11. * Brook framework is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation; either
  14. * version 2.1 of the License, or (at your option) any later version.
  15. *
  16. * Brook framework is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with Brook framework; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. *)
  25. program Test_StringMap;
  26. {$I Tests.inc}
  27. {$IFDEF FPC}
  28. {$CODEPAGE UTF8}
  29. {$ENDIF}
  30. uses
  31. SysUtils,
  32. libsagui,
  33. BrookLibraryLoader,
  34. BrookStringMap,
  35. Test;
  36. type
  37. TLocalStringMap = class(TBrookStringMap)
  38. private
  39. FOperation: TBrookStringMapOperation;
  40. protected
  41. procedure DoChange(AOperation: TBrookStringMapOperation); override;
  42. public
  43. procedure LocalDestroy;
  44. property Operation: TBrookStringMapOperation read FOperation;
  45. end;
  46. procedure TLocalStringMap.DoChange(AOperation: TBrookStringMapOperation);
  47. begin
  48. FOperation := AOperation;
  49. inherited DoChange(AOperation);
  50. end;
  51. procedure TLocalStringMap.LocalDestroy;
  52. begin
  53. inherited Destroy;
  54. SgLib.Check;
  55. { checks if the handle was really freed and 'nilified'. }
  56. Assert(not Assigned(Handle));
  57. sg_strmap_cleanup(Handle);
  58. end;
  59. procedure Test_StringMapNameValue;
  60. var
  61. VPair: TBrookStringPair;
  62. begin
  63. VPair := TBrookStringPair.Create('', '');
  64. Assert(VPair.Name.IsEmpty);
  65. Assert(VPair.Value.IsEmpty);
  66. VPair := TBrookStringPair.Create('abc', '123');
  67. Assert(VPair.Name.Equals('abc'));
  68. Assert(VPair.Value.Equals('123'));
  69. end;
  70. procedure Test_StringMapClearOnDestroy;
  71. var
  72. VMapHandle: Pointer;
  73. VMap: TBrookStringMap;
  74. begin
  75. VMapHandle := nil;
  76. VMap := TBrookStringMap.Create(@VMapHandle);
  77. try
  78. Assert(VMap.ClearOnDestroy);
  79. VMap.ClearOnDestroy := False;
  80. VMap.Add('abc', '123');
  81. VMap.Add('def', '456');
  82. SgLib.Check;
  83. Assert(sg_strmap_count(VMapHandle) = 2);
  84. finally
  85. VMap.Free;
  86. end;
  87. Assert(sg_strmap_count(VMapHandle) = 2);
  88. sg_strmap_cleanup(@VMapHandle);
  89. VMapHandle := nil;
  90. VMap := TLocalStringMap.Create(@VMapHandle);
  91. try
  92. VMap.Add('abc', '123');
  93. VMap.Add('def', '456');
  94. SgLib.Check;
  95. Assert(sg_strmap_count(VMapHandle) = 2);
  96. finally
  97. VMap.Free;
  98. end;
  99. Assert(sg_strmap_count(VMapHandle) = 0);
  100. end;
  101. procedure Test_StringMapOnChange;
  102. var
  103. VMapHandle: Pointer;
  104. VMap: TLocalStringMap;
  105. begin
  106. VMapHandle := nil;
  107. VMap := TLocalStringMap.Create(@VMapHandle);
  108. try
  109. Assert(VMap.Operation = sgmoNone);
  110. VMap.Add('abc', '123');
  111. Assert(VMap.Operation = sgmoAdd);
  112. VMap.AddOrSet('def', '456');
  113. Assert(VMap.Operation = sgmoAddOrSet);
  114. VMap.Remove('abc');
  115. Assert(VMap.Operation = sgmoRemove);
  116. VMap.Clear;
  117. Assert(VMap.Operation = sgmoNone);
  118. finally
  119. VMap.Free;
  120. end;
  121. end;
  122. procedure Test_StringMapHandle(AMap: TBrookStringMap);
  123. var
  124. VMapHandle: Pointer;
  125. VMap: TBrookStringMap;
  126. begin
  127. AMap.Clear;
  128. AMap.Add('abc', '123');
  129. Assert(Assigned(AMap.Handle));
  130. VMap := TBrookStringMap.Create(AMap.Handle);
  131. try
  132. Assert(VMap.Handle = AMap.Handle);
  133. finally
  134. VMap.Free;
  135. end;
  136. VMapHandle := nil;
  137. VMap := TBrookStringMap.Create(@VMapHandle);
  138. try
  139. VMap.Add('abc', '123');
  140. Assert(Assigned(VMap.Handle));
  141. Assert(VMap.Handle <> AMap.Handle);
  142. finally
  143. VMap.Free;
  144. end;
  145. end;
  146. procedure Test_StringMapAdd(AMap: TBrookStringMap; const AName, AValue: string);
  147. begin
  148. AMap.Clear;
  149. Assert(AMap.Count = 0);
  150. AMap.Add('', AValue);
  151. Assert(AMap.Count = 1);
  152. AMap.Clear;
  153. AMap.Add(AName, '');
  154. Assert(AMap.Count = 1);
  155. AMap.Clear;
  156. AMap.Add(AName, AValue);
  157. AMap.Add(AName, AValue);
  158. Assert(AMap.Count = 2);
  159. end;
  160. procedure Test_StringMapAddOrSet(AMap: TBrookStringMap; const AName,
  161. AValue: string);
  162. begin
  163. AMap.Clear;
  164. Assert(AMap.Count = 0);
  165. AMap.AddOrSet('', AValue);
  166. Assert(AMap.Count = 1);
  167. AMap.Clear;
  168. AMap.AddOrSet(AName, '');
  169. Assert(AMap.Count = 1);
  170. AMap.Clear;
  171. AMap.AddOrSet(AName, AValue);
  172. AMap.AddOrSet(AName, AValue);
  173. Assert(AMap.Count = 1);
  174. end;
  175. procedure Test_StringMapFind(AMap: TBrookStringMap; const AName,
  176. AValue: string);
  177. var
  178. VPair: TBrookStringPair;
  179. begin
  180. AMap.Clear;
  181. Assert(AMap.Count = 0);
  182. AMap.Add(AName, AValue);
  183. Assert(AMap.Count = 1);
  184. Assert(not AMap.Find('', VPair));
  185. Assert(VPair.Name.IsEmpty);
  186. Assert(VPair.Value.IsEmpty);
  187. Assert(not AMap.Find('xxx', VPair));
  188. Assert(VPair.Name.IsEmpty);
  189. Assert(VPair.Value.IsEmpty);
  190. Assert(not AMap.Find('yyy', VPair));
  191. Assert(VPair.Name.IsEmpty);
  192. Assert(VPair.Value.IsEmpty);
  193. AMap.Add('', '');
  194. AMap.Add('xxx', 'yyy');
  195. AMap.Add('yyy', 'xxx');
  196. Assert(AMap.Count = 4);
  197. Assert(AMap.Find(AName, VPair));
  198. Assert((VPair.Name = AName) and (VPair.Value = AValue));
  199. Assert(AMap.Find('', VPair));
  200. Assert((VPair.Name.IsEmpty) and (VPair.Value.IsEmpty));
  201. Assert(AMap.Find('xxx', VPair));
  202. Assert(VPair.Name.Equals('xxx') and VPair.Value.Equals('yyy'));
  203. Assert(AMap.Find('yyy', VPair));
  204. Assert(VPair.Name.Equals('yyy') and VPair.Value.Equals('xxx'));
  205. end;
  206. procedure Test_StringMapGet(AMap: TBrookStringMap; const AName,
  207. AValue: string);
  208. begin
  209. AMap.Clear;
  210. Assert(AMap.Count = 0);
  211. AMap.Add(AName, AValue);
  212. Assert(AMap.Count = 1);
  213. Assert(AMap.Get('').IsEmpty);
  214. Assert(AMap.Get('xxx').IsEmpty);
  215. Assert(AMap.Get('yyy').IsEmpty);
  216. AMap.Add('', '');
  217. AMap.Add('xxx', 'yyy');
  218. AMap.Add('yyy', 'xxx');
  219. Assert(AMap.Count = 4);
  220. Assert(AMap.Get(AName).Equals(AValue));
  221. Assert(AMap.Get('').IsEmpty);
  222. Assert(AMap.Get('xxx').Equals('yyy'));
  223. Assert(AMap.Get('yyy').Equals('xxx'));
  224. end;
  225. procedure Test_StringMapRemove(AMap: TBrookStringMap; const AName,
  226. AValue: string);
  227. var
  228. VPair: TBrookStringPair;
  229. begin
  230. AMap.Clear;
  231. Assert(AMap.Count = 0);
  232. AMap.Add(AName, AValue);
  233. Assert(AMap.Count = 1);
  234. AMap.Remove('');
  235. Assert(AMap.Count = 1);
  236. AMap.Remove('xxx');
  237. Assert(AMap.Count = 1);
  238. AMap.Remove('yyy');
  239. Assert(AMap.Count = 1);
  240. AMap.Add('', '');
  241. AMap.Add('xxx', 'yyy');
  242. AMap.Add('yyy', 'xxx');
  243. Assert(AMap.Count = 4);
  244. Assert(AMap.Find(AName, VPair));
  245. AMap.Remove(AName);
  246. Assert(AMap.Count = 3);
  247. Assert(not AMap.Find(AName, VPair));
  248. Assert(AMap.Find('', VPair));
  249. AMap.Remove('');
  250. Assert(AMap.Count = 2);
  251. Assert(not AMap.Find('', VPair));
  252. Assert(AMap.Find('xxx', VPair));
  253. AMap.Remove('xxx');
  254. Assert(AMap.Count = 1);
  255. Assert(not AMap.Find('xxx', VPair));
  256. Assert(AMap.Find('yyy', VPair));
  257. AMap.Remove('yyy');
  258. Assert(AMap.Count = 0);
  259. Assert(not AMap.Find('yyy', VPair));
  260. end;
  261. function StringMapIterateEmpty(AData: Pointer;
  262. APair: TBrookStringPair): Integer;
  263. begin
  264. Result := 0;
  265. end;
  266. function StringMapIterate123(AData: Pointer; APair: TBrookStringPair): Integer;
  267. begin
  268. Result := 123;
  269. end;
  270. function StringMapIterateConcat(AData: Pointer;
  271. APair: TBrookStringPair): Integer;
  272. var
  273. S: PString absolute AData;
  274. begin
  275. S^ := Concat(S^, APair.Name, APair.Value);
  276. Result := 0;
  277. end;
  278. procedure DoStringMapIterate(const AArgs: array of const);
  279. begin
  280. TBrookStringMap(AArgs[0].VObject).Iterate(StringMapIterate123, nil);
  281. end;
  282. procedure Test_StringMapIterate(AMap: TBrookStringMap);
  283. var
  284. S: string;
  285. begin
  286. AMap.Clear;
  287. AMap.Add('abc', '123');
  288. AMap.Add('def', '456');
  289. AMap.Iterate(StringMapIterateEmpty, nil);
  290. AssertOSExcept(DoStringMapIterate, 123, [AMap]);
  291. S := '';
  292. AMap.Iterate(StringMapIterateConcat, @S);
  293. Assert(S.Equals('abc123def456'));
  294. end;
  295. function StringMapSortEmpty(AData: Pointer; APairA,
  296. APairB: TBrookStringPair): Integer;
  297. var
  298. S: PString absolute AData;
  299. begin
  300. S^ := Concat(S^, S^);
  301. Result := 0;
  302. end;
  303. function StringMapSortNameDesc(AData: Pointer; APairA,
  304. APairB: TBrookStringPair): Integer;
  305. begin
  306. Result := CompareStr(APairB.Name, APairA.Name);
  307. end;
  308. function StringMapSortNameAsc(AData: Pointer; APairA,
  309. APairB: TBrookStringPair): Integer;
  310. begin
  311. Result := CompareStr(APairA.Name, APairB.Name);
  312. end;
  313. function StringMapSortValueDesc(AData: Pointer; APairA,
  314. APairB: TBrookStringPair): Integer;
  315. begin
  316. Result := CompareStr(APairB.Value, APairA.Value);
  317. end;
  318. function StringMapSortValueAsc(AData: Pointer; APairA,
  319. APairB: TBrookStringPair): Integer;
  320. begin
  321. Result := CompareStr(APairA.Value, APairB.Value);
  322. end;
  323. procedure Test_StringMapSort(AMap: TBrookStringMap);
  324. var
  325. S: string;
  326. begin
  327. AMap.Clear;
  328. AMap.Add('abc', '123');
  329. AMap.Add('def', '456');
  330. S := 'abc';
  331. AMap.Sort(StringMapSortEmpty, @S);
  332. Assert(S.Equals('abcabc'));
  333. S := '';
  334. AMap.Iterate(StringMapIterateConcat, @S);
  335. Assert(S.Equals('abc123def456'));
  336. AMap.Sort(StringMapSortNameDesc, nil);
  337. S := '';
  338. AMap.Iterate(StringMapIterateConcat, @S);
  339. Assert(S.Equals('def456abc123'));
  340. AMap.Sort(StringMapSortNameAsc, nil);
  341. S := '';
  342. AMap.Iterate(StringMapIterateConcat, @S);
  343. Assert(S.Equals('abc123def456'));
  344. AMap.Sort(StringMapSortValueDesc, nil);
  345. S := '';
  346. AMap.Iterate(StringMapIterateConcat, @S);
  347. Assert(S.Equals('def456abc123'));
  348. AMap.Sort(StringMapSortValueAsc, nil);
  349. S := '';
  350. AMap.Iterate(StringMapIterateConcat, @S);
  351. Assert(S.Equals('abc123def456'));
  352. end;
  353. procedure Test_StringMapCount(AMap: TBrookStringMap; const AName,
  354. AValue: string);
  355. begin
  356. AMap.Clear;
  357. Assert(AMap.Count = 0);
  358. AMap.Add(AName, AValue);
  359. Assert(AMap.Count = 1);
  360. AMap.Add('xxx', 'yyy');
  361. Assert(AMap.Count = 2);
  362. AMap.Add('yyy', 'xxx');
  363. Assert(AMap.Count = 3);
  364. AMap.Add(AName, AValue);
  365. Assert(AMap.Count = 4);
  366. AMap.Remove(AName);
  367. Assert(AMap.Count = 3);
  368. AMap.Clear;
  369. Assert(AMap.Count = 0);
  370. end;
  371. procedure Test_StringMapTryValue(AMap: TBrookStringMap; const AName,
  372. AValue: string);
  373. var
  374. S: string;
  375. begin
  376. AMap.Clear;
  377. Assert(AMap.Count = 0);
  378. AMap.Add(AName, AValue);
  379. Assert(AMap.Count = 1);
  380. Assert(not AMap.TryValue('', S));
  381. Assert(S.IsEmpty);
  382. Assert(not AMap.TryValue('xxx', S));
  383. Assert(S.IsEmpty);
  384. Assert(not AMap.TryValue('yyy', S));
  385. Assert(S.IsEmpty);
  386. AMap.Add('', '');
  387. AMap.Add('xxx', 'yyy');
  388. AMap.Add('yyy', 'xxx');
  389. Assert(AMap.Count = 4);
  390. Assert(AMap.TryValue(AName, S));
  391. Assert(S = AValue);
  392. Assert(AMap.TryValue('', S));
  393. Assert(S.IsEmpty);
  394. Assert(AMap.TryValue('xxx', S));
  395. Assert(S.Equals('yyy'));
  396. Assert(AMap.TryValue('yyy', S));
  397. Assert(S.Equals('xxx'));
  398. end;
  399. procedure Test_StringMapFirst(AMap: TBrookStringMap);
  400. var
  401. VPair: TBrookStringPair;
  402. begin
  403. AMap.Clear;
  404. AMap.Add('abc', '123');
  405. AMap.Add('def', '456');
  406. AMap.Add('xxx', 'yyy');
  407. AMap.First(VPair);
  408. Assert(VPair.Name.Equals('abc') and VPair.Value.Equals('123'));
  409. AMap.Next(VPair);
  410. AMap.Next(VPair);
  411. Assert(VPair.Name.Equals('xxx') and VPair.Value.Equals('yyy'));
  412. AMap.First(VPair);
  413. Assert(VPair.Name.Equals('abc') and VPair.Value.Equals('123'));
  414. end;
  415. procedure Test_StringMapValues(AMap: TBrookStringMap);
  416. begin
  417. AMap.Clear;
  418. Assert(AMap.Values['abc'].IsEmpty);
  419. AMap.Values['abc'] := '123';
  420. Assert(AMap.Values['abc'].Equals('123'));
  421. Assert(AMap.Values['def'].IsEmpty);
  422. AMap.Values['def'] := '456';
  423. Assert(AMap.Values['def'].Equals('456'));
  424. Assert(AMap.Values['xxx'].IsEmpty);
  425. AMap.Values['xxx'] := 'yyy';
  426. Assert(AMap.Values['xxx'].Equals('yyy'));
  427. Assert(AMap.Count = 3);
  428. AMap.Values['xxx'] := 'yyy';
  429. Assert(AMap.Count = 3);
  430. end;
  431. procedure Test_StringMapEOF(AMap: TBrookStringMap);
  432. var
  433. VPair: TBrookStringPair;
  434. begin
  435. AMap.Clear;
  436. AMap.Add('abc', '123');
  437. AMap.Add('def', '456');
  438. AMap.Add('xxx', 'yyy');
  439. AMap.First(VPair);
  440. Assert(not AMap.EOF);
  441. AMap.Next(VPair);
  442. Assert(not AMap.EOF);
  443. AMap.Next(VPair);
  444. Assert(not AMap.EOF);
  445. AMap.Next(VPair);
  446. Assert(AMap.EOF);
  447. AMap.Next(VPair);
  448. Assert(AMap.EOF);
  449. end;
  450. procedure Test_StringMapNext(AMap: TBrookStringMap);
  451. var
  452. S: string;
  453. VPair: TBrookStringPair;
  454. begin
  455. AMap.Clear;
  456. VPair := Default(TBrookStringPair);
  457. Assert(not AMap.Next(VPair));
  458. AMap.Add('abc', '123');
  459. AMap.Add('def', '456');
  460. AMap.Add('xxx', 'yyy');
  461. S := '';
  462. AMap.First(VPair);
  463. while not AMap.EOF do
  464. begin
  465. S := Concat(S, VPair.Name, VPair.Value);
  466. AMap.Next(VPair);
  467. end;
  468. Assert(S.Equals('abc123def456xxxyyy'));
  469. end;
  470. procedure Test_StringMapEnumerator(AMap: TBrookStringMap);
  471. var
  472. I: Byte;
  473. S: string;
  474. P: TBrookStringPair;
  475. begin
  476. AMap.Clear;
  477. for I := 1 to 3 do
  478. begin
  479. S := I.ToString;
  480. AMap.Add(Concat('name', S), Concat('value', S));
  481. end;
  482. I := 0;
  483. for P in AMap do
  484. begin
  485. S := Succ(I).ToString;
  486. Assert(P.Name.Equals(Concat('name', S)) and
  487. P.Value.Equals(Concat('value', S)));
  488. Inc(I);
  489. end;
  490. Assert(I = 3);
  491. end;
  492. procedure Test_StringMapToString(AMap: TBrookStringMap; const AName,
  493. AValue: string);
  494. begin
  495. AMap.Clear;
  496. Assert(AMap.ToString.IsEmpty);
  497. AMap.Add(AName, AValue);
  498. Assert(AMap.ToString = Concat(AName, '=', AValue, sLineBreak));
  499. AMap.Add('xxx', 'yyy');
  500. AMap.Add('yyy', 'xxx');
  501. Assert(AMap.ToString.Equals(Concat(AName, '=', AValue, sLineBreak,
  502. 'xxx=yyy', sLineBreak, 'yyy=xxx', sLineBreak)));
  503. end;
  504. procedure Test_StringMapClear(AMap: TBrookStringMap);
  505. begin
  506. AMap.Clear;
  507. Assert(AMap.Count = 0);
  508. AMap.Add('abc', '123');
  509. AMap.Add('def', '456');
  510. AMap.Add('xxx', 'yyy');
  511. Assert(AMap.Count = 3);
  512. AMap.Clear;
  513. Assert(AMap.Count = 0);
  514. AMap.Clear;
  515. Assert(AMap.Count = 0);
  516. end;
  517. const
  518. NAME = 'abç';
  519. VAL = 'déf';
  520. var
  521. VMapHandle: Pointer;
  522. VMap: TBrookStringMap;
  523. begin
  524. {$IF (NOT DEFINED(FPC)) AND DEFINED(DEBUG)}
  525. ReportMemoryLeaksOnShutdown := True;
  526. {$ENDIF}
  527. TBrookLibraryLoader.Load;
  528. Test_StringMapNameValue;
  529. Test_StringMapClearOnDestroy;
  530. Test_StringMapOnChange;
  531. VMapHandle := nil;
  532. VMap := TBrookStringMap.Create(@VMapHandle);
  533. try
  534. Test_StringMapHandle(VMap);
  535. Test_StringMapAdd(VMap, NAME, VAL);
  536. Test_StringMapAddOrSet(VMap, NAME, VAL);
  537. Test_StringMapFind(VMap, NAME, VAL);
  538. Test_StringMapGet(VMap, NAME, VAL);
  539. Test_StringMapRemove(VMap, NAME, VAL);
  540. Test_StringMapIterate(VMap);
  541. Test_StringMapSort(VMap);
  542. Test_StringMapCount(VMap, NAME, VAL);
  543. Test_StringMapTryValue(VMap, NAME, VAL);
  544. Test_StringMapFirst(VMap);
  545. Test_StringMapValues(VMap);
  546. Test_StringMapEOF(VMap);
  547. Test_StringMapNext(VMap);
  548. Test_StringMapEnumerator(VMap);
  549. Test_StringMapToString(VMap, NAME, VAL);
  550. Test_StringMapClear(VMap);
  551. finally
  552. VMap.Free;
  553. end;
  554. end.