Test_StringMap.dpr 15 KB

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