Test_HTTPResponse.dpr 22 KB

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