Test_HTTPResponse.dpr 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  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_clear(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_zsendfile2(res: Psg_httpres; level: cint; size: cuint64_t;
  218. max_size: cuint64_t; offset: cuint64_t; const filename: Pcchar;
  219. const disposition: Pcchar; status: cuint): cint; cdecl;
  220. var
  221. D: string;
  222. begin
  223. Assert(res = FakeResponseHandle);
  224. if FakeResponse.ResponseAlreadySent then
  225. Exit(EALREADY);
  226. Assert(level = 1);
  227. Assert(size = 0);
  228. Assert(max_size = 0);
  229. Assert(offset = 0);
  230. Assert(TMarshal.ToString(filename) = 'fake_filename');
  231. D := TMarshal.ToString(disposition);
  232. Assert((D = 'attachment') or (D = 'inline'));
  233. Assert(status = 200);
  234. FakeResponse.WasCompressed := True;
  235. FakeResponse.ResponseAlreadySent := True;
  236. Result := FakeResponse.ErrorCode;
  237. end;
  238. function fake_httpres_sendfile2(res: Psg_httpres; size: cuint64_t;
  239. max_size: cuint64_t; offset: cuint64_t; const filename: Pcchar;
  240. const disposition: Pcchar; status: cuint): cint; cdecl;
  241. var
  242. D: string;
  243. begin
  244. Assert(res = FakeResponseHandle);
  245. if FakeResponse.ResponseAlreadySent then
  246. Exit(EALREADY);
  247. Assert(size = 0);
  248. Assert(max_size = 0);
  249. Assert(offset = 0);
  250. Assert(TMarshal.ToString(filename) = 'fake_filename');
  251. D := TMarshal.ToString(disposition);
  252. Assert((D = 'attachment') or (D = 'inline'));
  253. Assert(status = 200);
  254. FakeResponse.WasCompressed := False;
  255. FakeResponse.ResponseAlreadySent := True;
  256. Result := FakeResponse.ErrorCode;
  257. end;
  258. function fake_httpres_is_empty(res: Psg_httpres): cbool; cdecl;
  259. begin
  260. Assert(res = FakeResponseHandle);
  261. Result := FakeResponse.Empty;
  262. end;
  263. procedure AssignFakeAPI; inline;
  264. begin
  265. sg_httpres_headers := fake_httpres_headers;
  266. sg_httpres_set_cookie := fake_httpres_set_cookie;
  267. sg_httpres_zsendbinary := fake_httpres_zsendbinary;
  268. sg_httpres_sendbinary := fake_httpres_sendbinary;
  269. sg_httpres_zsendfile := fake_httpres_zsendfile;
  270. sg_httpres_sendfile := fake_httpres_sendfile;
  271. sg_httpres_zsendstream := fake_httpres_zsendstream;
  272. sg_httpres_sendstream := fake_httpres_sendstream;
  273. sg_httpres_clear := fake_httpres_clear;
  274. sg_httpres_zsendfile2 := fake_httpres_zsendfile2;
  275. sg_httpres_sendfile2 := fake_httpres_sendfile2;
  276. sg_httpres_is_empty := fake_httpres_is_empty;
  277. end;
  278. procedure Test_HTTPResponseCreate;
  279. var
  280. R: TBrookHTTPResponse;
  281. begin
  282. AssignFakeAPI;
  283. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  284. try
  285. Assert(R.Handle = FakeResponseHandle);
  286. finally
  287. R.Free;
  288. end;
  289. end;
  290. procedure DoHTTPResponseSetCookieLibNotLoaded(const AArgs: array of const);
  291. begin
  292. TBrookHTTPResponse(AArgs[0].VObject).SetCookie('fake_name', 'fake_val');
  293. end;
  294. procedure DoHTTPResponseSetCookieInvalidArgument(const AArgs: array of const);
  295. begin
  296. TBrookHTTPResponse(AArgs[0].VObject).SetCookie('', '');
  297. end;
  298. procedure Test_HTTPResponseSetCookie;
  299. var
  300. R: TBrookHTTPResponse;
  301. begin
  302. AssignFakeAPI;
  303. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  304. try
  305. TBrookLibraryLoader.Unload;
  306. try
  307. AssertExcept(DoHTTPResponseSetCookieLibNotLoaded, ESgLibNotLoaded,
  308. Format(SSgLibNotLoaded, [IfThen(SgLib.GetLastName = '',
  309. SG_LIB_NAME, SgLib.GetLastName)]), [R]);
  310. finally
  311. TBrookLibraryLoader.Load;
  312. end;
  313. AssignFakeAPI;
  314. AssertOSExcept(DoHTTPResponseSetCookieInvalidArgument, EINVAL, [R]);
  315. R.SetCookie('fake_name', 'fake_val');
  316. finally
  317. R.Free;
  318. end;
  319. end;
  320. procedure DoHTTPResponseSendError(const AArgs: array of const);
  321. begin
  322. TBrookHTTPResponse(AArgs[0].VObject).Send('fake_val', 'fake_content_type', 200);
  323. end;
  324. procedure Test_HTTPResponseSend;
  325. var
  326. R: TBrookHTTPResponse;
  327. begin
  328. AssignFakeAPI;
  329. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  330. try
  331. R.Compressed := True;
  332. FakeResponse.ResponseAlreadySent := False;
  333. FakeResponse.ErrorCode := 0;
  334. R.Send('fake_val', 'fake_content_type', 200);
  335. Assert(FakeResponse.WasCompressed);
  336. FakeResponse.ErrorCode := -1;
  337. FakeResponse.ResponseAlreadySent := False;
  338. AssertExcept(DoHTTPResponseSendError, EBrookHTTPResponse,
  339. SBrookZLibError, [R]);
  340. R.Compressed := False;
  341. FakeResponse.ErrorCode := 0;
  342. FakeResponse.ResponseAlreadySent := False;
  343. R.Send('fake_val', 'fake_content_type', 200);
  344. Assert(not FakeResponse.WasCompressed);
  345. AssertExcept(DoHTTPResponseSendError, EBrookHTTPResponse,
  346. SBrookResponseAlreadySent, [R]);
  347. FakeResponse.ResponseAlreadySent := False;
  348. FakeResponse.ErrorCode := EINVAL;
  349. AssertOSExcept(DoHTTPResponseSendError, EINVAL, [R]);
  350. finally
  351. R.Free;
  352. end;
  353. end;
  354. procedure Test_HTTPResponseSendFmt;
  355. var
  356. R: TBrookHTTPResponse;
  357. begin
  358. AssignFakeAPI;
  359. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  360. try
  361. FakeResponse.ErrorCode := 0;
  362. FakeResponse.ResponseAlreadySent := False;
  363. R.SendFmt('%s_%s', ['fake', 'val'], 'fake_content_type', 200);
  364. Assert(FakeResponse.ResponseAlreadySent);
  365. finally
  366. R.Free;
  367. end;
  368. end;
  369. procedure DoHTTPResponseSendBinaryError(const AArgs: array of const);
  370. var
  371. B: TBytes;
  372. begin
  373. B := BytesOf('fake_val');
  374. TBrookHTTPResponse(AArgs[0].VObject).SendBinary(@B[0], Length(B),
  375. 'fake_content_type', 200);
  376. end;
  377. procedure Test_HTTPResponseSendBinary;
  378. var
  379. R: TBrookHTTPResponse;
  380. B: TBytes;
  381. begin
  382. AssignFakeAPI;
  383. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  384. try
  385. R.Compressed := True;
  386. FakeResponse.ResponseAlreadySent := False;
  387. FakeResponse.ErrorCode := 0;
  388. B := BytesOf('fake_val');
  389. R.SendBinary(@B[0], Length(B), 'fake_content_type', 200);
  390. Assert(FakeResponse.WasCompressed);
  391. FakeResponse.ErrorCode := -1;
  392. FakeResponse.ResponseAlreadySent := False;
  393. AssertExcept(DoHTTPResponseSendBinaryError, EBrookHTTPResponse,
  394. SBrookZLibError, [R]);
  395. R.Compressed := False;
  396. FakeResponse.ErrorCode := 0;
  397. FakeResponse.ResponseAlreadySent := False;
  398. R.SendBinary(@B[0], Length(B), 'fake_content_type', 200);
  399. Assert(not FakeResponse.WasCompressed);
  400. AssertExcept(DoHTTPResponseSendBinaryError, EBrookHTTPResponse,
  401. SBrookResponseAlreadySent, [R]);
  402. FakeResponse.ResponseAlreadySent := False;
  403. FakeResponse.ErrorCode := EINVAL;
  404. AssertOSExcept(DoHTTPResponseSendBinaryError, EINVAL, [R]);
  405. finally
  406. R.Free;
  407. end;
  408. end;
  409. procedure Test_HTTPResponseSendBytes;
  410. var
  411. R: TBrookHTTPResponse;
  412. B: TBytes;
  413. begin
  414. AssignFakeAPI;
  415. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  416. try
  417. FakeResponse.ErrorCode := 0;
  418. FakeResponse.ResponseAlreadySent := False;
  419. B := BytesOf('fake_val');
  420. R.SendBytes(B, Length(B), 'fake_content_type', 200);
  421. Assert(FakeResponse.ResponseAlreadySent);
  422. finally
  423. R.Free;
  424. end;
  425. end;
  426. procedure DoHTTPResponseSendFileError(const AArgs: array of const);
  427. begin
  428. TBrookHTTPResponse(AArgs[0].VObject).SendFile(123, 456, 789, 'fake_filename',
  429. True, 200);
  430. end;
  431. procedure Test_HTTPResponseSendFile;
  432. var
  433. R: TBrookHTTPResponse;
  434. begin
  435. AssignFakeAPI;
  436. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  437. try
  438. R.Compressed := True;
  439. FakeResponse.ResponseAlreadySent := False;
  440. FakeResponse.ErrorCode := 0;
  441. R.SendFile(123, 456, 789, 'fake_filename', True, 200);
  442. Assert(FakeResponse.WasCompressed);
  443. FakeResponse.ErrorCode := -1;
  444. FakeResponse.ResponseAlreadySent := False;
  445. AssertExcept(DoHTTPResponseSendFileError, EBrookHTTPResponse,
  446. SBrookZLibError, [R]);
  447. R.Compressed := False;
  448. FakeResponse.ErrorCode := 0;
  449. FakeResponse.ResponseAlreadySent := False;
  450. R.SendFile(123, 456, 789, 'fake_filename', True, 200);
  451. Assert(not FakeResponse.WasCompressed);
  452. AssertExcept(DoHTTPResponseSendFileError, EBrookHTTPResponse,
  453. SBrookResponseAlreadySent, [R]);
  454. FakeResponse.ResponseAlreadySent := False;
  455. FakeResponse.ErrorCode := ENOENT;
  456. AssertExcept(DoHTTPResponseSendFileError, EFileNotFoundException,
  457. SFileNotFound, [R]);
  458. FakeResponse.ResponseAlreadySent := False;
  459. FakeResponse.ErrorCode := EINVAL;
  460. AssertOSExcept(DoHTTPResponseSendFileError, EINVAL, [R]);
  461. finally
  462. R.Free;
  463. end;
  464. end;
  465. procedure DoHTTPResponseSendStreamError(const AArgs: array of const);
  466. begin
  467. TBrookHTTPResponse(AArgs[0].VObject).SendStream(
  468. TFakeStringStream.Create('fake_val'), True, 200);
  469. end;
  470. procedure Test_HTTPResponseSendStream;
  471. var
  472. R: TBrookHTTPResponse;
  473. begin
  474. AssignFakeAPI;
  475. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  476. try
  477. R.Compressed := True;
  478. FakeResponse.ResponseAlreadySent := False;
  479. FakeResponse.ErrorCode := 0;
  480. R.SendStream(TFakeStringStream.Create('fake_val'), True, 200);
  481. Assert(FakeResponse.WasCompressed);
  482. FakeResponse.ErrorCode := -1;
  483. FakeResponse.ResponseAlreadySent := False;
  484. AssertExcept(DoHTTPResponseSendStreamError, EBrookHTTPResponse,
  485. SBrookZLibError, [R]);
  486. R.Compressed := False;
  487. FakeResponse.ErrorCode := 0;
  488. FakeResponse.ResponseAlreadySent := False;
  489. R.SendStream(TFakeStringStream.Create('fake_val'), True, 200);
  490. Assert(not FakeResponse.WasCompressed);
  491. AssertExcept(DoHTTPResponseSendStreamError, EBrookHTTPResponse,
  492. SBrookResponseAlreadySent, [R]);
  493. FakeResponse.ResponseAlreadySent := False;
  494. FakeResponse.ErrorCode := EINVAL;
  495. AssertOSExcept(DoHTTPResponseSendStreamError, EINVAL, [R]);
  496. FakeResponse.ErrorCode := 0;
  497. FakeResponse.ResponseAlreadySent := False;
  498. R.SendStream(TFakeStringStream.Create('fake_val'), 200);
  499. finally
  500. R.Free;
  501. end;
  502. end;
  503. function fake_httpres_sendbinary_empty(res: Psg_httpres; buf: Pcvoid;
  504. size: csize_t; const content_type: Pcchar; status: cuint): cint; cdecl;
  505. var
  506. C: String;
  507. begin
  508. Assert(res = FakeResponseHandle);
  509. Assert(Length(Pcchar(buf)) = 0);
  510. Assert(size = 0);
  511. C := TMarshal.ToString(content_type);
  512. if not C.IsEmpty then
  513. Assert(C = 'fake_content_type');
  514. Assert(status = 204);
  515. Result := FakeResponse.ErrorCode;
  516. end;
  517. procedure Test_HTTPResponseSendEmpty;
  518. var
  519. R: TBrookHTTPResponse;
  520. begin
  521. AssignFakeAPI;
  522. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  523. try
  524. FakeResponse.ErrorCode := 0;
  525. sg_httpres_sendbinary := fake_httpres_sendbinary_empty;
  526. R.SendEmpty('fake_content_type');
  527. R.SendEmpty;
  528. TBrookLibraryLoader.Unload;
  529. TBrookLibraryLoader.Load;
  530. finally
  531. R.Free;
  532. end;
  533. end;
  534. procedure DoHTTPResponseSendAndRedirectInvalidHTTPStatus(
  535. const AArgs: array of const);
  536. begin
  537. TBrookHTTPResponse(AArgs[0].VObject).SendAndRedirect('fake_val',
  538. 'fake_destination', 'fake_content_type', AArgs[1].VInteger);
  539. end;
  540. procedure Test_HTTPResponseSendAndRedirect;
  541. var
  542. R: TBrookHTTPResponse;
  543. begin
  544. AssignFakeAPI;
  545. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  546. try
  547. FakeResponse.ErrorCode := 0;
  548. FakeResponse.ResponseAlreadySent := False;
  549. AssertExcept(DoHTTPResponseSendAndRedirectInvalidHTTPStatus,
  550. EBrookHTTPResponse, Format(SBrookInvalidHTTPStatus, [50]), [R, 50]);
  551. AssertExcept(DoHTTPResponseSendAndRedirectInvalidHTTPStatus,
  552. EBrookHTTPResponse, Format(SBrookInvalidHTTPStatus, [1000]), [R, 1000]);
  553. Assert(R.Headers['Location'].IsEmpty);
  554. R.SendAndRedirect('fake_val', 'fake_destination', 'fake_content_type', 302);
  555. Assert(FakeResponse.LastStatus = 302);
  556. Assert(R.Headers['Location'] = 'fake_destination');
  557. R.Clear;
  558. R.Headers['Location'] := 'foo';
  559. R.SendAndRedirect('fake_val', 'fake_destination2', 'fake_content_type', 307);
  560. Assert(FakeResponse.LastStatus = 307);
  561. Assert(R.Headers['Location'] = 'fake_destination2');
  562. R.Clear;
  563. R.SendAndRedirect('fake_val', 'fake_destination2', 'fake_content_type');
  564. Assert(FakeResponse.LastStatus = 302);
  565. Assert(R.Headers['Location'] = 'fake_destination2');
  566. finally
  567. R.Free;
  568. end;
  569. end;
  570. procedure DoHTTPResponseDownloadError(const AArgs: array of const);
  571. begin
  572. TBrookHTTPResponse(AArgs[0].VObject).Download('fake_filename');
  573. end;
  574. procedure Test_HTTPResponseDownload;
  575. var
  576. R: TBrookHTTPResponse;
  577. begin
  578. AssignFakeAPI;
  579. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  580. try
  581. R.Compressed := True;
  582. FakeResponse.ResponseAlreadySent := False;
  583. FakeResponse.ErrorCode := 0;
  584. R.Download('fake_filename');
  585. Assert(FakeResponse.WasCompressed);
  586. FakeResponse.ErrorCode := -1;
  587. FakeResponse.ResponseAlreadySent := False;
  588. AssertExcept(DoHTTPResponseDownloadError, EBrookHTTPResponse,
  589. SBrookZLibError, [R]);
  590. R.Compressed := False;
  591. FakeResponse.ErrorCode := 0;
  592. FakeResponse.ResponseAlreadySent := False;
  593. R.Download('fake_filename');
  594. Assert(not FakeResponse.WasCompressed);
  595. AssertExcept(DoHTTPResponseDownloadError, EBrookHTTPResponse,
  596. SBrookResponseAlreadySent, [R]);
  597. FakeResponse.ResponseAlreadySent := False;
  598. FakeResponse.ErrorCode := ENOENT;
  599. AssertExcept(DoHTTPResponseDownloadError, EFileNotFoundException,
  600. SFileNotFound, [R]);
  601. FakeResponse.ResponseAlreadySent := False;
  602. FakeResponse.ErrorCode := EINVAL;
  603. AssertOSExcept(DoHTTPResponseDownloadError, EINVAL, [R]);
  604. finally
  605. R.Free;
  606. end;
  607. end;
  608. procedure DoHTTPResponseRenderError(const AArgs: array of const);
  609. begin
  610. TBrookHTTPResponse(AArgs[0].VObject).Render('fake_filename');
  611. end;
  612. procedure Test_HTTPResponseRender;
  613. var
  614. R: TBrookHTTPResponse;
  615. begin
  616. AssignFakeAPI;
  617. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  618. try
  619. R.Compressed := True;
  620. FakeResponse.ResponseAlreadySent := False;
  621. FakeResponse.ErrorCode := 0;
  622. R.Render('fake_filename');
  623. Assert(FakeResponse.WasCompressed);
  624. FakeResponse.ErrorCode := -1;
  625. FakeResponse.ResponseAlreadySent := False;
  626. AssertExcept(DoHTTPResponseRenderError, EBrookHTTPResponse,
  627. SBrookZLibError, [R]);
  628. R.Compressed := False;
  629. FakeResponse.ErrorCode := 0;
  630. FakeResponse.ResponseAlreadySent := False;
  631. R.Render('fake_filename');
  632. Assert(not FakeResponse.WasCompressed);
  633. AssertExcept(DoHTTPResponseRenderError, EBrookHTTPResponse,
  634. SBrookResponseAlreadySent, [R]);
  635. FakeResponse.ResponseAlreadySent := False;
  636. FakeResponse.ErrorCode := ENOENT;
  637. AssertExcept(DoHTTPResponseRenderError, EFileNotFoundException,
  638. SFileNotFound, [R]);
  639. FakeResponse.ResponseAlreadySent := False;
  640. FakeResponse.ErrorCode := EINVAL;
  641. AssertOSExcept(DoHTTPResponseRenderError, EINVAL, [R]);
  642. finally
  643. R.Free;
  644. end;
  645. end;
  646. procedure DoHTTPResponseClearError(const AArgs: array of const);
  647. begin
  648. TBrookHTTPResponse(AArgs[0].VObject).Clear;
  649. end;
  650. procedure Test_HTTPResponseClear;
  651. var
  652. R: TBrookHTTPResponse;
  653. begin
  654. AssignFakeAPI;
  655. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  656. try
  657. TBrookLibraryLoader.Unload;
  658. try
  659. AssertExcept(DoHTTPResponseClearError, ESgLibNotLoaded,
  660. Format(SSgLibNotLoaded, [IfThen(SgLib.GetLastName = '', SG_LIB_NAME,
  661. SgLib.GetLastName)]), [R]);
  662. finally
  663. TBrookLibraryLoader.Load;
  664. end;
  665. AssignFakeAPI;
  666. FakeResponse.ErrorCode := 0;
  667. FakeResponse.ResponseAlreadySent := False;
  668. R.Send('fake_val', 'fake_content_type', 200);
  669. Assert(FakeResponse.ResponseAlreadySent);
  670. R.Clear;
  671. Assert(not FakeResponse.ResponseAlreadySent);
  672. FakeResponse.ResponseAlreadySent := False;
  673. FakeResponse.ErrorCode := EINVAL;
  674. AssertOSExcept(DoHTTPResponseClearError, EINVAL, [R]);
  675. finally
  676. R.Free;
  677. end;
  678. end;
  679. procedure Test_HTTPResponseIsEmpty;
  680. var
  681. R: TBrookHTTPResponse;
  682. begin
  683. AssignFakeAPI;
  684. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  685. try
  686. FakeResponse.Empty := False;
  687. Assert(not R.IsEmpty);
  688. FakeResponse.Empty := True;
  689. Assert(R.IsEmpty);
  690. finally
  691. R.Free;
  692. end;
  693. end;
  694. procedure Test_HTTPResponseCompressed;
  695. var
  696. R: TBrookHTTPResponse;
  697. begin
  698. AssignFakeAPI;
  699. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  700. try
  701. Assert(not R.Compressed);
  702. R.Compressed := not R.Compressed;
  703. Assert(R.Compressed);
  704. finally
  705. R.Free;
  706. end;
  707. end;
  708. procedure Test_HTTPResponseHeaders;
  709. var
  710. R: TBrookHTTPResponse;
  711. begin
  712. AssignFakeAPI;
  713. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  714. try
  715. Assert(R.Headers.Count = 0);
  716. R.Headers.Add('foo', 'bar');
  717. R.Headers.Add('bar', 'foo');
  718. Assert(R.Headers.Count = 2);
  719. finally
  720. R.Free;
  721. end;
  722. end;
  723. procedure Test_HTTPResponseCookies;
  724. var
  725. R: TBrookHTTPResponse;
  726. begin
  727. AssignFakeAPI;
  728. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  729. try
  730. Assert(R.Cookies.Count = 0);
  731. R.Cookies.Add;
  732. R.Cookies.Add;
  733. Assert(R.Cookies.Count = 2);
  734. finally
  735. R.Free;
  736. end;
  737. end;
  738. procedure Test_HTTPResponseEmpty;
  739. var
  740. R: TBrookHTTPResponse;
  741. begin
  742. AssignFakeAPI;
  743. R := TBrookHTTPResponse.Create(FakeResponseHandle);
  744. try
  745. FakeResponse.Empty := False;
  746. Assert(not R.Empty);
  747. FakeResponse.Empty := True;
  748. Assert(R.Empty);
  749. finally
  750. R.Free;
  751. end;
  752. end;
  753. begin
  754. {$IF (NOT DEFINED(FPC)) AND DEFINED(DEBUG)}
  755. ReportMemoryLeaksOnShutdown := True;
  756. {$ENDIF}
  757. TBrookLibraryLoader.Load;
  758. FakeResponse := TFakeResponse.Create;
  759. try
  760. FakeResponseHandle := FakeResponse;
  761. Test_HTTPResponseCreate;
  762. // Test_HTTPResponseDestroy - not required
  763. Test_HTTPResponseSetCookie;
  764. Test_HTTPResponseSend;
  765. Test_HTTPResponseSendFmt;
  766. Test_HTTPResponseSendBinary;
  767. Test_HTTPResponseSendBytes;
  768. Test_HTTPResponseSendFile;
  769. Test_HTTPResponseSendStream;
  770. Test_HTTPResponseSendEmpty;
  771. Test_HTTPResponseSendAndRedirect;
  772. Test_HTTPResponseDownload;
  773. Test_HTTPResponseRender;
  774. Test_HTTPResponseClear;
  775. Test_HTTPResponseIsEmpty;
  776. Test_HTTPResponseCompressed;
  777. Test_HTTPResponseHeaders;
  778. Test_HTTPResponseCookies;
  779. Test_HTTPResponseEmpty;
  780. finally
  781. TBrookLibraryLoader.Unload;
  782. FakeResponse.Free;
  783. end;
  784. end.