Test_HTTPResponse.dpr 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962
  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_HTTPResponse;
  26. {$I Tests.inc}
  27. uses
  28. SysConst,
  29. SysUtils,
  30. StrUtils,
  31. Classes,
  32. Platform,
  33. Marshalling,
  34. libsagui,
  35. BrookLibraryLoader,
  36. BrookHTTPResponse,
  37. Test;
  38. type
  39. TFakeResponse = class
  40. public
  41. ResponseAlreadySent: Boolean;
  42. WasCompressed: Boolean;
  43. LastStatus: Word;
  44. ErrorCode: Integer;
  45. Empty: Boolean;
  46. end;
  47. TFakeStringStream = class(TStringStream)
  48. public
  49. Freed: Boolean;
  50. destructor Destroy; override;
  51. end;
  52. destructor TFakeStringStream.Destroy;
  53. begin
  54. inherited Destroy;
  55. Freed := True;
  56. end;
  57. var
  58. FakeResponse: TFakeResponse;
  59. FakeResponseHandle: Pointer;
  60. FakeHandle: Pointer;
  61. function fake_httpres_headers(res: Psg_httpres): PPsg_strmap; cdecl;
  62. begin
  63. Assert(res = FakeResponseHandle);
  64. FakeHandle := nil;
  65. Result := @FakeHandle;
  66. end;
  67. function fake_httpres_set_cookie(res: Psg_httpres; const name: Pcchar;
  68. const val: Pcchar): cint; cdecl;
  69. var
  70. N: string;
  71. begin
  72. Assert(res = FakeResponseHandle);
  73. N := TMarshal.ToString(name);
  74. if N.IsEmpty then
  75. Exit(EINVAL);
  76. Assert(N = 'fake_name');
  77. Assert(TMarshal.ToString(val) = 'fake_val');
  78. Result := 0;
  79. end;
  80. function fake_httpres_zsendbinary(res: Psg_httpres; buf: Pcvoid; size: csize_t;
  81. const content_type: Pcchar; status: cuint): cint; cdecl;
  82. var
  83. S: string;
  84. begin
  85. Assert(res = FakeResponseHandle);
  86. if FakeResponse.ResponseAlreadySent then
  87. Exit(EALREADY);
  88. S := TMarshal.ToString(buf);
  89. SetLength(S, size);
  90. Assert(S = 'fake_val');
  91. Assert(size = csize_t(Length(S)));
  92. Assert(TMarshal.ToString(content_type) = 'fake_content_type');
  93. Assert(status = 200);
  94. FakeResponse.WasCompressed := True;
  95. FakeResponse.ResponseAlreadySent := True;
  96. Result := FakeResponse.ErrorCode;
  97. end;
  98. function fake_httpres_sendbinary(res: Psg_httpres; buf: Pcvoid; size: csize_t;
  99. const content_type: Pcchar; status: cuint): cint; cdecl;
  100. var
  101. S: string;
  102. begin
  103. Assert(res = FakeResponseHandle);
  104. if FakeResponse.ResponseAlreadySent then
  105. Exit(EALREADY);
  106. S := TMarshal.ToString(buf);
  107. SetLength(S, size);
  108. Assert(S = 'fake_val');
  109. Assert(size = csize_t(Length(S)));
  110. Assert(TMarshal.ToString(content_type) = 'fake_content_type');
  111. Assert((status = 200) or (status = 302) or (status = 307));
  112. FakeResponse.WasCompressed := False;
  113. FakeResponse.ResponseAlreadySent := True;
  114. FakeResponse.LastStatus := status;
  115. Result := FakeResponse.ErrorCode;
  116. end;
  117. function fake_httpres_zsendfile(res: Psg_httpres; size: cuint64_t;
  118. max_size: cuint64_t; offset: cuint64_t; const filename: Pcchar;
  119. downloaded: cbool; status: cuint): cint; cdecl;
  120. begin
  121. Assert(res = FakeResponseHandle);
  122. if FakeResponse.ResponseAlreadySent then
  123. Exit(EALREADY);
  124. Assert(size = 123);
  125. Assert(max_size = 456);
  126. Assert(offset = 789);
  127. Assert(TMarshal.ToString(filename) = 'fake_filename');
  128. Assert(downloaded);
  129. Assert(status = 200);
  130. FakeResponse.WasCompressed := True;
  131. FakeResponse.ResponseAlreadySent := True;
  132. Result := FakeResponse.ErrorCode;
  133. end;
  134. function fake_httpres_sendfile(res: Psg_httpres; size: cuint64_t;
  135. max_size: cuint64_t; offset: cuint64_t; const filename: Pcchar;
  136. downloaded: cbool; status: cuint): cint; cdecl;
  137. begin
  138. Assert(res = FakeResponseHandle);
  139. if FakeResponse.ResponseAlreadySent then
  140. Exit(EALREADY);
  141. Assert(size = 123);
  142. Assert(max_size = 456);
  143. Assert(offset = 789);
  144. Assert(TMarshal.ToString(filename) = 'fake_filename');
  145. Assert(downloaded);
  146. Assert(status = 200);
  147. FakeResponse.WasCompressed := False;
  148. FakeResponse.ResponseAlreadySent := True;
  149. Result := FakeResponse.ErrorCode;
  150. end;
  151. function fake_httpres_zsendstream(res: Psg_httpres; read_cb: sg_read_cb;
  152. handle: Pcvoid; free_cb: sg_free_cb; status: cuint): cint; cdecl;
  153. var
  154. S: TFakeStringStream;
  155. B: TBytes{$IFDEF FPC}= nil{$ENDIF};
  156. Z: csize_t;
  157. begin
  158. Assert(res = FakeResponseHandle);
  159. if FakeResponse.ResponseAlreadySent then
  160. begin
  161. if Assigned(free_cb) then
  162. free_cb(handle);
  163. Exit(EALREADY);
  164. end;
  165. Assert(Assigned(read_cb));
  166. SetLength(B, 256);
  167. Z := read_cb(handle, 0, @B[0], Length(B));
  168. SetLength(B, Z);
  169. Assert(StringOf(B) = 'fake_val');
  170. S := TFakeStringStream(handle);
  171. Assert(not S.Freed);
  172. Assert(Assigned(free_cb));
  173. free_cb(handle);
  174. Assert(S.Freed);
  175. Assert(status = 200);
  176. FakeResponse.WasCompressed := True;
  177. FakeResponse.ResponseAlreadySent := True;
  178. Result := FakeResponse.ErrorCode;
  179. end;
  180. function fake_httpres_sendstream(res: Psg_httpres; size: cuint64_t;
  181. read_cb: sg_read_cb; handle: Pcvoid; free_cb: sg_free_cb;
  182. status: cuint): cint; cdecl;
  183. var
  184. S: TFakeStringStream;
  185. B: TBytes{$IFDEF FPC}= nil{$ENDIF};
  186. Z: csize_t;
  187. begin
  188. Assert(res = FakeResponseHandle);
  189. if FakeResponse.ResponseAlreadySent then
  190. begin
  191. if Assigned(free_cb) then
  192. free_cb(handle);
  193. Exit(EALREADY);
  194. end;
  195. Assert(size = 0);
  196. Assert(Assigned(read_cb));
  197. SetLength(B, 256);
  198. Z := read_cb(handle, 0, @B[0], Length(B));
  199. SetLength(B, Z);
  200. Assert(StringOf(B) = 'fake_val');
  201. S := TFakeStringStream(handle);
  202. Assert(not S.Freed);
  203. Assert(Assigned(free_cb));
  204. free_cb(handle);
  205. Assert(S.Freed);
  206. Assert(status = 200);
  207. FakeResponse.WasCompressed := False;
  208. FakeResponse.ResponseAlreadySent := True;
  209. Result := FakeResponse.ErrorCode;
  210. end;
  211. function fake_httpres_reset(res: Psg_httpres): cint; cdecl;
  212. begin
  213. Assert(res = FakeResponseHandle);
  214. FakeResponse.ResponseAlreadySent := False;
  215. Result := FakeResponse.ErrorCode;
  216. end;
  217. function fake_httpres_clear(res: Psg_httpres): cint; cdecl;
  218. begin
  219. Assert(res = FakeResponseHandle);
  220. FakeResponse.ResponseAlreadySent := False;
  221. Result := FakeResponse.ErrorCode;
  222. end;
  223. function fake_httpres_zsendfile2(res: Psg_httpres; level: cint; size: cuint64_t;
  224. max_size: cuint64_t; offset: cuint64_t; const filename: Pcchar;
  225. const disposition: Pcchar; status: cuint): cint; cdecl;
  226. var
  227. D: string;
  228. begin
  229. Assert(res = FakeResponseHandle);
  230. if FakeResponse.ResponseAlreadySent then
  231. Exit(EALREADY);
  232. Assert(level = 1);
  233. Assert(size = 0);
  234. Assert(max_size = 0);
  235. Assert(offset = 0);
  236. Assert(TMarshal.ToString(filename) = 'fake_filename');
  237. D := TMarshal.ToString(disposition);
  238. Assert((D = 'attachment') or (D = 'inline'));
  239. Assert(status = 200);
  240. FakeResponse.WasCompressed := True;
  241. FakeResponse.ResponseAlreadySent := True;
  242. Result := FakeResponse.ErrorCode;
  243. end;
  244. function fake_httpres_sendfile2(res: Psg_httpres; size: cuint64_t;
  245. max_size: cuint64_t; offset: cuint64_t; const filename: Pcchar;
  246. const disposition: Pcchar; status: cuint): cint; cdecl;
  247. var
  248. D: string;
  249. begin
  250. Assert(res = FakeResponseHandle);
  251. if FakeResponse.ResponseAlreadySent then
  252. Exit(EALREADY);
  253. Assert(size = 0);
  254. Assert(max_size = 0);
  255. Assert(offset = 0);
  256. Assert(TMarshal.ToString(filename) = 'fake_filename');
  257. D := TMarshal.ToString(disposition);
  258. Assert((D = 'attachment') or (D = 'inline'));
  259. Assert(status = 200);
  260. FakeResponse.WasCompressed := False;
  261. FakeResponse.ResponseAlreadySent := True;
  262. Result := FakeResponse.ErrorCode;
  263. end;
  264. function fake_httpres_is_empty(res: Psg_httpres): cbool; cdecl;
  265. begin
  266. Assert(res = FakeResponseHandle);
  267. Result := FakeResponse.Empty;
  268. end;
  269. procedure AssignFakeAPI; {$IFNDEF DEBUG}inline;{$ENDIF}
  270. begin
  271. sg_httpres_headers := fake_httpres_headers;
  272. sg_httpres_set_cookie := fake_httpres_set_cookie;
  273. sg_httpres_zsendbinary := fake_httpres_zsendbinary;
  274. sg_httpres_sendbinary := fake_httpres_sendbinary;
  275. sg_httpres_zsendfile := fake_httpres_zsendfile;
  276. sg_httpres_sendfile := fake_httpres_sendfile;
  277. sg_httpres_zsendstream := fake_httpres_zsendstream;
  278. sg_httpres_sendstream := fake_httpres_sendstream;
  279. sg_httpres_reset := fake_httpres_reset;
  280. sg_httpres_clear := fake_httpres_clear;
  281. sg_httpres_zsendfile2 := fake_httpres_zsendfile2;
  282. sg_httpres_sendfile2 := fake_httpres_sendfile2;
  283. sg_httpres_is_empty := fake_httpres_is_empty;
  284. end;
  285. procedure Test_HTTPResponseCreate;
  286. var
  287. R: TBrookHTTPResponse;
  288. begin
  289. AssignFakeAPI;
  290. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  291. try
  292. Assert(R.Handle = FakeResponseHandle);
  293. finally
  294. R.Free;
  295. end;
  296. end;
  297. procedure DoHTTPResponseSetCookieLibNotLoaded(const AArgs: array of const);
  298. begin
  299. TBrookHTTPResponse(AArgs[0].VObject).SetCookie('fake_name', 'fake_val');
  300. end;
  301. procedure DoHTTPResponseSetCookieInvalidArgument(const AArgs: array of const);
  302. begin
  303. TBrookHTTPResponse(AArgs[0].VObject).SetCookie('', '');
  304. end;
  305. procedure Test_HTTPResponseSetCookie;
  306. var
  307. R: TBrookHTTPResponse;
  308. begin
  309. AssignFakeAPI;
  310. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  311. try
  312. FakeResponse.ErrorCode := 0;
  313. TBrookLibraryLoader.Unload;
  314. try
  315. AssertExcept(DoHTTPResponseSetCookieLibNotLoaded, ESgLibNotLoaded,
  316. Format(SSgLibNotLoaded, [IfThen(SgLib.GetLastName = '',
  317. SG_LIB_NAME, SgLib.GetLastName)]), [R]);
  318. finally
  319. TBrookLibraryLoader.Load;
  320. end;
  321. AssignFakeAPI;
  322. AssertOSExcept(DoHTTPResponseSetCookieInvalidArgument, EINVAL, [R]);
  323. R.SetCookie('fake_name', 'fake_val');
  324. finally
  325. R.Free;
  326. end;
  327. end;
  328. procedure DoHTTPResponseSendError(const AArgs: array of const);
  329. begin
  330. TBrookHTTPResponse(AArgs[0].VObject).Send('fake_val', 'fake_content_type', 200);
  331. end;
  332. procedure Test_HTTPResponseSend;
  333. var
  334. R: TBrookHTTPResponse;
  335. begin
  336. AssignFakeAPI;
  337. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  338. try
  339. R.Compressed := True;
  340. FakeResponse.ResponseAlreadySent := False;
  341. FakeResponse.ErrorCode := 0;
  342. R.Send('fake_val', 'fake_content_type', 200);
  343. Assert(FakeResponse.WasCompressed);
  344. TBrookLibraryLoader.Unload;
  345. try
  346. AssertExcept(DoHTTPResponseSendError, ESgLibNotLoaded,
  347. Format(SSgLibNotLoaded, [IfThen(SgLib.GetLastName = '',
  348. SG_LIB_NAME, SgLib.GetLastName)]), [R]);
  349. finally
  350. TBrookLibraryLoader.Load;
  351. end;
  352. AssignFakeAPI;
  353. FakeResponse.ErrorCode := -1;
  354. FakeResponse.ResponseAlreadySent := False;
  355. AssertExcept(DoHTTPResponseSendError, EBrookHTTPResponse,
  356. SBrookZLibError, [R]);
  357. R.Compressed := False;
  358. FakeResponse.ErrorCode := 0;
  359. FakeResponse.ResponseAlreadySent := False;
  360. R.Send('fake_val', 'fake_content_type', 200);
  361. Assert(not FakeResponse.WasCompressed);
  362. AssertExcept(DoHTTPResponseSendError, EBrookHTTPResponse,
  363. SBrookResponseAlreadySent, [R]);
  364. FakeResponse.ResponseAlreadySent := False;
  365. FakeResponse.ErrorCode := EINVAL;
  366. AssertOSExcept(DoHTTPResponseSendError, EINVAL, [R]);
  367. finally
  368. R.Free;
  369. end;
  370. end;
  371. procedure Test_HTTPResponseSendFmt;
  372. var
  373. R: TBrookHTTPResponse;
  374. begin
  375. AssignFakeAPI;
  376. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  377. try
  378. FakeResponse.ErrorCode := 0;
  379. FakeResponse.ResponseAlreadySent := False;
  380. R.SendFmt('%s_%s', ['fake', 'val'], 'fake_content_type', 200);
  381. Assert(FakeResponse.ResponseAlreadySent);
  382. finally
  383. R.Free;
  384. end;
  385. end;
  386. procedure DoHTTPResponseSendBinaryError(const AArgs: array of const);
  387. var
  388. B: TBytes;
  389. begin
  390. B := BytesOf('fake_val');
  391. TBrookHTTPResponse(AArgs[0].VObject).SendBinary(@B[0], Length(B),
  392. 'fake_content_type', 200);
  393. end;
  394. procedure Test_HTTPResponseSendBinary;
  395. var
  396. R: TBrookHTTPResponse;
  397. B: TBytes;
  398. begin
  399. AssignFakeAPI;
  400. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  401. try
  402. R.Compressed := True;
  403. FakeResponse.ResponseAlreadySent := False;
  404. FakeResponse.ErrorCode := 0;
  405. B := BytesOf('fake_val');
  406. R.SendBinary(@B[0], Length(B), 'fake_content_type', 200);
  407. Assert(FakeResponse.WasCompressed);
  408. TBrookLibraryLoader.Unload;
  409. try
  410. AssertExcept(DoHTTPResponseSendBinaryError, ESgLibNotLoaded,
  411. Format(SSgLibNotLoaded, [IfThen(SgLib.GetLastName = '',
  412. SG_LIB_NAME, SgLib.GetLastName)]), [R]);
  413. finally
  414. TBrookLibraryLoader.Load;
  415. end;
  416. AssignFakeAPI;
  417. FakeResponse.ErrorCode := -1;
  418. FakeResponse.ResponseAlreadySent := False;
  419. AssertExcept(DoHTTPResponseSendBinaryError, EBrookHTTPResponse,
  420. SBrookZLibError, [R]);
  421. R.Compressed := False;
  422. FakeResponse.ErrorCode := 0;
  423. FakeResponse.ResponseAlreadySent := False;
  424. R.SendBinary(@B[0], Length(B), 'fake_content_type', 200);
  425. Assert(not FakeResponse.WasCompressed);
  426. AssertExcept(DoHTTPResponseSendBinaryError, EBrookHTTPResponse,
  427. SBrookResponseAlreadySent, [R]);
  428. FakeResponse.ResponseAlreadySent := False;
  429. FakeResponse.ErrorCode := EINVAL;
  430. AssertOSExcept(DoHTTPResponseSendBinaryError, EINVAL, [R]);
  431. finally
  432. R.Free;
  433. end;
  434. end;
  435. procedure Test_HTTPResponseSendBytes;
  436. var
  437. R: TBrookHTTPResponse;
  438. B: TBytes;
  439. begin
  440. AssignFakeAPI;
  441. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  442. try
  443. FakeResponse.ErrorCode := 0;
  444. FakeResponse.ResponseAlreadySent := False;
  445. B := BytesOf('fake_val');
  446. R.SendBytes(B, Length(B), 'fake_content_type', 200);
  447. Assert(FakeResponse.ResponseAlreadySent);
  448. finally
  449. R.Free;
  450. end;
  451. end;
  452. procedure DoHTTPResponseSendFileError(const AArgs: array of const);
  453. begin
  454. TBrookHTTPResponse(AArgs[0].VObject).SendFile(123, 456, 789, 'fake_filename',
  455. True, 200);
  456. end;
  457. procedure Test_HTTPResponseSendFile;
  458. var
  459. R: TBrookHTTPResponse;
  460. begin
  461. AssignFakeAPI;
  462. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  463. try
  464. R.Compressed := True;
  465. FakeResponse.ResponseAlreadySent := False;
  466. FakeResponse.ErrorCode := 0;
  467. R.SendFile(123, 456, 789, 'fake_filename', True, 200);
  468. Assert(FakeResponse.WasCompressed);
  469. TBrookLibraryLoader.Unload;
  470. try
  471. AssertExcept(DoHTTPResponseSendFileError, ESgLibNotLoaded,
  472. Format(SSgLibNotLoaded, [IfThen(SgLib.GetLastName = '',
  473. SG_LIB_NAME, SgLib.GetLastName)]), [R]);
  474. finally
  475. TBrookLibraryLoader.Load;
  476. end;
  477. AssignFakeAPI;
  478. FakeResponse.ErrorCode := -1;
  479. FakeResponse.ResponseAlreadySent := False;
  480. AssertExcept(DoHTTPResponseSendFileError, EBrookHTTPResponse,
  481. SBrookZLibError, [R]);
  482. R.Compressed := False;
  483. FakeResponse.ErrorCode := 0;
  484. FakeResponse.ResponseAlreadySent := False;
  485. R.SendFile(123, 456, 789, 'fake_filename', True, 200);
  486. Assert(not FakeResponse.WasCompressed);
  487. AssertExcept(DoHTTPResponseSendFileError, EBrookHTTPResponse,
  488. SBrookResponseAlreadySent, [R]);
  489. FakeResponse.ResponseAlreadySent := False;
  490. FakeResponse.ErrorCode := ENOENT;
  491. AssertExcept(DoHTTPResponseSendFileError, EFileNotFoundException,
  492. SFileNotFound, [R]);
  493. FakeResponse.ResponseAlreadySent := False;
  494. FakeResponse.ErrorCode := EINVAL;
  495. AssertOSExcept(DoHTTPResponseSendFileError, EINVAL, [R]);
  496. finally
  497. R.Free;
  498. end;
  499. end;
  500. procedure DoHTTPResponseSendStreamError(const AArgs: array of const);
  501. var
  502. S: TFakeStringStream;
  503. begin
  504. S := TFakeStringStream.Create('fake_val');
  505. try
  506. TBrookHTTPResponse(AArgs[0].VObject).SendStream(S, True, 200);
  507. finally
  508. Assert(S.Freed);
  509. end;
  510. end;
  511. procedure Test_HTTPResponseSendStream;
  512. var
  513. R: TBrookHTTPResponse;
  514. begin
  515. AssignFakeAPI;
  516. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  517. try
  518. R.Compressed := True;
  519. FakeResponse.ResponseAlreadySent := False;
  520. FakeResponse.ErrorCode := 0;
  521. R.SendStream(TFakeStringStream.Create('fake_val'), True, 200);
  522. Assert(FakeResponse.WasCompressed);
  523. TBrookLibraryLoader.Unload;
  524. try
  525. AssertExcept(DoHTTPResponseSendStreamError, ESgLibNotLoaded,
  526. Format(SSgLibNotLoaded, [IfThen(SgLib.GetLastName = '',
  527. SG_LIB_NAME, SgLib.GetLastName)]), [R]);
  528. finally
  529. TBrookLibraryLoader.Load;
  530. end;
  531. AssignFakeAPI;
  532. FakeResponse.ErrorCode := -1;
  533. FakeResponse.ResponseAlreadySent := False;
  534. AssertExcept(DoHTTPResponseSendStreamError, EBrookHTTPResponse,
  535. SBrookZLibError, [R]);
  536. R.Compressed := False;
  537. FakeResponse.ErrorCode := 0;
  538. FakeResponse.ResponseAlreadySent := False;
  539. R.SendStream(TFakeStringStream.Create('fake_val'), True, 200);
  540. Assert(not FakeResponse.WasCompressed);
  541. AssertExcept(DoHTTPResponseSendStreamError, EBrookHTTPResponse,
  542. SBrookResponseAlreadySent, [R]);
  543. FakeResponse.ResponseAlreadySent := False;
  544. FakeResponse.ErrorCode := EINVAL;
  545. AssertOSExcept(DoHTTPResponseSendStreamError, EINVAL, [R]);
  546. FakeResponse.ErrorCode := 0;
  547. FakeResponse.ResponseAlreadySent := False;
  548. R.SendStream(TFakeStringStream.Create('fake_val'), 200);
  549. finally
  550. R.Free;
  551. end;
  552. end;
  553. function fake_httpres_sendbinary_empty(res: Psg_httpres; buf: Pcvoid;
  554. size: csize_t; const content_type: Pcchar; status: cuint): cint; cdecl;
  555. var
  556. C: String;
  557. begin
  558. Assert(res = FakeResponseHandle);
  559. Assert(Length(Pcchar(buf)) = 0);
  560. Assert(size = 0);
  561. C := TMarshal.ToString(content_type);
  562. if not C.IsEmpty then
  563. Assert(C = 'fake_content_type');
  564. Assert(status = 204);
  565. Result := FakeResponse.ErrorCode;
  566. end;
  567. procedure Test_HTTPResponseSendEmpty;
  568. var
  569. R: TBrookHTTPResponse;
  570. begin
  571. AssignFakeAPI;
  572. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  573. try
  574. FakeResponse.ErrorCode := 0;
  575. sg_httpres_sendbinary := fake_httpres_sendbinary_empty;
  576. R.SendEmpty('fake_content_type');
  577. R.SendEmpty;
  578. TBrookLibraryLoader.Unload;
  579. TBrookLibraryLoader.Load;
  580. finally
  581. R.Free;
  582. end;
  583. end;
  584. procedure DoHTTPResponseSendAndRedirectInvalidHTTPStatus(
  585. const AArgs: array of const);
  586. begin
  587. TBrookHTTPResponse(AArgs[0].VObject).SendAndRedirect('fake_val',
  588. 'fake_destination', 'fake_content_type', AArgs[1].VInteger);
  589. end;
  590. procedure Test_HTTPResponseSendAndRedirect;
  591. var
  592. R: TBrookHTTPResponse;
  593. begin
  594. AssignFakeAPI;
  595. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  596. try
  597. FakeResponse.ErrorCode := 0;
  598. FakeResponse.ResponseAlreadySent := False;
  599. AssertExcept(DoHTTPResponseSendAndRedirectInvalidHTTPStatus,
  600. EBrookHTTPResponse, Format(SBrookInvalidHTTPStatus, [50]), [R, 50]);
  601. AssertExcept(DoHTTPResponseSendAndRedirectInvalidHTTPStatus,
  602. EBrookHTTPResponse, Format(SBrookInvalidHTTPStatus, [1000]), [R, 1000]);
  603. Assert(R.Headers['Location'].IsEmpty);
  604. R.SendAndRedirect('fake_val', 'fake_destination', 'fake_content_type', 302);
  605. Assert(FakeResponse.LastStatus = 302);
  606. Assert(R.Headers['Location'] = 'fake_destination');
  607. R.Clear;
  608. R.Headers['Location'] := 'foo';
  609. R.SendAndRedirect('fake_val', 'fake_destination2', 'fake_content_type', 307);
  610. Assert(FakeResponse.LastStatus = 307);
  611. Assert(R.Headers['Location'] = 'fake_destination2');
  612. R.Clear;
  613. R.SendAndRedirect('fake_val', 'fake_destination2', 'fake_content_type');
  614. Assert(FakeResponse.LastStatus = 302);
  615. Assert(R.Headers['Location'] = 'fake_destination2');
  616. finally
  617. R.Free;
  618. end;
  619. end;
  620. procedure DoHTTPResponseDownloadError(const AArgs: array of const);
  621. begin
  622. TBrookHTTPResponse(AArgs[0].VObject).Download('fake_filename');
  623. end;
  624. procedure Test_HTTPResponseDownload;
  625. var
  626. R: TBrookHTTPResponse;
  627. begin
  628. AssignFakeAPI;
  629. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  630. try
  631. R.Compressed := True;
  632. FakeResponse.ResponseAlreadySent := False;
  633. FakeResponse.ErrorCode := 0;
  634. R.Download('fake_filename');
  635. Assert(FakeResponse.WasCompressed);
  636. TBrookLibraryLoader.Unload;
  637. try
  638. AssertExcept(DoHTTPResponseDownloadError, ESgLibNotLoaded,
  639. Format(SSgLibNotLoaded, [IfThen(SgLib.GetLastName = '',
  640. SG_LIB_NAME, SgLib.GetLastName)]), [R]);
  641. finally
  642. TBrookLibraryLoader.Load;
  643. end;
  644. AssignFakeAPI;
  645. FakeResponse.ErrorCode := -1;
  646. FakeResponse.ResponseAlreadySent := False;
  647. AssertExcept(DoHTTPResponseDownloadError, EBrookHTTPResponse,
  648. SBrookZLibError, [R]);
  649. R.Compressed := False;
  650. FakeResponse.ErrorCode := 0;
  651. FakeResponse.ResponseAlreadySent := False;
  652. R.Download('fake_filename');
  653. Assert(not FakeResponse.WasCompressed);
  654. AssertExcept(DoHTTPResponseDownloadError, EBrookHTTPResponse,
  655. SBrookResponseAlreadySent, [R]);
  656. FakeResponse.ResponseAlreadySent := False;
  657. FakeResponse.ErrorCode := ENOENT;
  658. AssertExcept(DoHTTPResponseDownloadError, EFileNotFoundException,
  659. SFileNotFound, [R]);
  660. FakeResponse.ResponseAlreadySent := False;
  661. FakeResponse.ErrorCode := EINVAL;
  662. AssertOSExcept(DoHTTPResponseDownloadError, EINVAL, [R]);
  663. finally
  664. R.Free;
  665. end;
  666. end;
  667. procedure DoHTTPResponseRenderError(const AArgs: array of const);
  668. begin
  669. TBrookHTTPResponse(AArgs[0].VObject).Render('fake_filename');
  670. end;
  671. procedure Test_HTTPResponseRender;
  672. var
  673. R: TBrookHTTPResponse;
  674. begin
  675. AssignFakeAPI;
  676. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  677. try
  678. R.Compressed := True;
  679. FakeResponse.ResponseAlreadySent := False;
  680. FakeResponse.ErrorCode := 0;
  681. R.Render('fake_filename');
  682. Assert(FakeResponse.WasCompressed);
  683. TBrookLibraryLoader.Unload;
  684. try
  685. AssertExcept(DoHTTPResponseRenderError, ESgLibNotLoaded,
  686. Format(SSgLibNotLoaded, [IfThen(SgLib.GetLastName = '',
  687. SG_LIB_NAME, SgLib.GetLastName)]), [R]);
  688. finally
  689. TBrookLibraryLoader.Load;
  690. end;
  691. AssignFakeAPI;
  692. FakeResponse.ErrorCode := -1;
  693. FakeResponse.ResponseAlreadySent := False;
  694. AssertExcept(DoHTTPResponseRenderError, EBrookHTTPResponse,
  695. SBrookZLibError, [R]);
  696. R.Compressed := False;
  697. FakeResponse.ErrorCode := 0;
  698. FakeResponse.ResponseAlreadySent := False;
  699. R.Render('fake_filename');
  700. Assert(not FakeResponse.WasCompressed);
  701. AssertExcept(DoHTTPResponseRenderError, EBrookHTTPResponse,
  702. SBrookResponseAlreadySent, [R]);
  703. FakeResponse.ResponseAlreadySent := False;
  704. FakeResponse.ErrorCode := ENOENT;
  705. AssertExcept(DoHTTPResponseRenderError, EFileNotFoundException,
  706. SFileNotFound, [R]);
  707. FakeResponse.ResponseAlreadySent := False;
  708. FakeResponse.ErrorCode := EINVAL;
  709. AssertOSExcept(DoHTTPResponseRenderError, EINVAL, [R]);
  710. finally
  711. R.Free;
  712. end;
  713. end;
  714. procedure DoHTTPResponseResetError(const AArgs: array of const);
  715. begin
  716. TBrookHTTPResponse(AArgs[0].VObject).Reset;
  717. end;
  718. procedure Test_HTTPResponseReset;
  719. var
  720. R: TBrookHTTPResponse;
  721. begin
  722. AssignFakeAPI;
  723. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  724. try
  725. FakeResponse.ErrorCode := 0;
  726. FakeResponse.ResponseAlreadySent := False;
  727. R.Send('fake_val', 'fake_content_type', 200);
  728. Assert(FakeResponse.ResponseAlreadySent);
  729. R.Reset;
  730. Assert(not FakeResponse.ResponseAlreadySent);
  731. TBrookLibraryLoader.Unload;
  732. try
  733. AssertExcept(DoHTTPResponseResetError, ESgLibNotLoaded,
  734. Format(SSgLibNotLoaded, [IfThen(SgLib.GetLastName = '', SG_LIB_NAME,
  735. SgLib.GetLastName)]), [R]);
  736. finally
  737. TBrookLibraryLoader.Load;
  738. end;
  739. AssignFakeAPI;
  740. FakeResponse.ResponseAlreadySent := False;
  741. FakeResponse.ErrorCode := EINVAL;
  742. AssertOSExcept(DoHTTPResponseResetError, EINVAL, [R]);
  743. finally
  744. R.Free;
  745. end;
  746. end;
  747. procedure DoHTTPResponseClearError(const AArgs: array of const);
  748. begin
  749. TBrookHTTPResponse(AArgs[0].VObject).Clear;
  750. end;
  751. procedure Test_HTTPResponseClear;
  752. var
  753. R: TBrookHTTPResponse;
  754. begin
  755. AssignFakeAPI;
  756. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  757. try
  758. FakeResponse.ErrorCode := 0;
  759. FakeResponse.ResponseAlreadySent := False;
  760. R.Send('fake_val', 'fake_content_type', 200);
  761. Assert(FakeResponse.ResponseAlreadySent);
  762. R.Clear;
  763. Assert(not FakeResponse.ResponseAlreadySent);
  764. TBrookLibraryLoader.Unload;
  765. try
  766. AssertExcept(DoHTTPResponseClearError, ESgLibNotLoaded,
  767. Format(SSgLibNotLoaded, [IfThen(SgLib.GetLastName = '', SG_LIB_NAME,
  768. SgLib.GetLastName)]), [R]);
  769. finally
  770. TBrookLibraryLoader.Load;
  771. end;
  772. AssignFakeAPI;
  773. FakeResponse.ResponseAlreadySent := False;
  774. FakeResponse.ErrorCode := EINVAL;
  775. AssertOSExcept(DoHTTPResponseClearError, EINVAL, [R]);
  776. finally
  777. R.Free;
  778. end;
  779. end;
  780. procedure DoHTTPResponseIsEmptyNotLoaded(const AArgs: array of const);
  781. begin
  782. TBrookHTTPResponse(AArgs[0].VObject).IsEmpty;
  783. end;
  784. procedure Test_HTTPResponseIsEmpty;
  785. var
  786. R: TBrookHTTPResponse;
  787. begin
  788. AssignFakeAPI;
  789. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  790. try
  791. FakeResponse.Empty := False;
  792. Assert(not R.IsEmpty);
  793. FakeResponse.Empty := True;
  794. Assert(R.IsEmpty);
  795. FakeResponse.ErrorCode := 0;
  796. TBrookLibraryLoader.Unload;
  797. try
  798. AssertExcept(DoHTTPResponseIsEmptyNotLoaded, ESgLibNotLoaded,
  799. Format(SSgLibNotLoaded, [IfThen(SgLib.GetLastName = '',
  800. SG_LIB_NAME, SgLib.GetLastName)]), [R]);
  801. AssignFakeAPI;
  802. finally
  803. TBrookLibraryLoader.Load;
  804. end;
  805. finally
  806. R.Free;
  807. end;
  808. end;
  809. procedure Test_HTTPResponseCompressed;
  810. var
  811. R: TBrookHTTPResponse;
  812. begin
  813. AssignFakeAPI;
  814. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  815. try
  816. Assert(not R.Compressed);
  817. R.Compressed := not R.Compressed;
  818. Assert(R.Compressed);
  819. finally
  820. R.Free;
  821. end;
  822. end;
  823. procedure Test_HTTPResponseHeaders;
  824. var
  825. R: TBrookHTTPResponse;
  826. begin
  827. AssignFakeAPI;
  828. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  829. try
  830. Assert(R.Headers.Count = 0);
  831. R.Headers.Add('foo', 'bar');
  832. R.Headers.Add('bar', 'foo');
  833. Assert(R.Headers.Count = 2);
  834. finally
  835. R.Free;
  836. end;
  837. end;
  838. procedure Test_HTTPResponseCookies;
  839. var
  840. R: TBrookHTTPResponse;
  841. begin
  842. AssignFakeAPI;
  843. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  844. try
  845. Assert(R.Cookies.Count = 0);
  846. R.Cookies.Add;
  847. R.Cookies.Add;
  848. Assert(R.Cookies.Count = 2);
  849. finally
  850. R.Free;
  851. end;
  852. end;
  853. procedure Test_HTTPResponseEmpty;
  854. var
  855. R: TBrookHTTPResponse;
  856. begin
  857. AssignFakeAPI;
  858. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  859. try
  860. FakeResponse.Empty := False;
  861. Assert(not R.Empty);
  862. FakeResponse.Empty := True;
  863. Assert(R.Empty);
  864. finally
  865. R.Free;
  866. end;
  867. end;
  868. begin
  869. {$IF (NOT DEFINED(FPC)) AND DEFINED(DEBUG)}
  870. ReportMemoryLeaksOnShutdown := True;
  871. {$ENDIF}
  872. TBrookLibraryLoader.Load;
  873. FakeResponse := TFakeResponse.Create;
  874. try
  875. FakeResponseHandle := FakeResponse;
  876. Test_HTTPResponseCreate;
  877. // Test_HTTPResponseDestroy - not required
  878. Test_HTTPResponseSetCookie;
  879. Test_HTTPResponseSend;
  880. Test_HTTPResponseSendFmt;
  881. Test_HTTPResponseSendBinary;
  882. Test_HTTPResponseSendBytes;
  883. Test_HTTPResponseSendFile;
  884. Test_HTTPResponseSendStream;
  885. Test_HTTPResponseSendEmpty;
  886. Test_HTTPResponseSendAndRedirect;
  887. Test_HTTPResponseDownload;
  888. Test_HTTPResponseRender;
  889. Test_HTTPResponseReset;
  890. Test_HTTPResponseClear;
  891. Test_HTTPResponseIsEmpty;
  892. Test_HTTPResponseCompressed;
  893. Test_HTTPResponseHeaders;
  894. Test_HTTPResponseCookies;
  895. Test_HTTPResponseEmpty;
  896. finally
  897. TBrookLibraryLoader.Unload;
  898. FakeResponse.Free;
  899. end;
  900. end.