tczipper.pp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. program tczipper;
  2. {
  3. This file is part of the Free Pascal packages.
  4. Copyright (c) 2012-2013 by the Free Pascal Development Team
  5. Created by Reinier Olislagers
  6. Tests zip/unzip functionality provided by the FPC zipper.pp unit.
  7. If passed a zip file name as first argument, it will try and decompress
  8. and list the contents of the zip file.
  9. See the file COPYING.FPC, included in this distribution,
  10. for details about the license.
  11. **********************************************************************}
  12. {$mode objfpc}{$h+}
  13. //Define this if you want to inspect the generated zips etc
  14. {$define KEEPTESTFILES}
  15. uses SysUtils, classes, zipper, unzip, zdeflate, zinflate, zip, md5, zstream, nullstream;
  16. type
  17. { TCallBackHandler }
  18. TCallBackHandler = class(TObject) //Callbacks used in zip/unzip processing
  19. private
  20. FPerformChecks: boolean;
  21. FOriginalContent: string;
  22. FShowContent: boolean;
  23. FStreamResult: boolean;
  24. public
  25. property PerformChecks: boolean read FPerformChecks write FPerformChecks; //If false, do not perform any consistency checks
  26. property OriginalContent: string read FOriginalContent write FOriginalContent; //Zip entry uncompressed content used in TestZipEntries
  27. property ShowContent: boolean read FShowContent write FShowContent; //Show contents of zip when extracting?
  28. property StreamResult: boolean read FStreamResult; //For handler to report success/failure
  29. procedure EndOfFile(Sender:TObject; const Ratio:double);
  30. procedure StartOfFile(Sender:TObject; const AFileName:string);
  31. procedure DoCreateZipOutputStream(Sender: TObject; var AStream: TStream;
  32. AItem: TFullZipFileEntry);
  33. procedure DoDoneOutZipStream(Sender: TObject; var AStream: TStream;
  34. AItem: TFullZipFileEntry); //Used to verify zip entry decompressed contents
  35. constructor Create;
  36. end;
  37. procedure TCallBackHandler.EndOfFile(Sender: TObject; const Ratio: double);
  38. begin
  39. writeln('End of file handler hit; ratio: '+floattostr(ratio));
  40. if (FPerformChecks) and (Ratio<0) then
  41. begin
  42. writeln('Found compression ratio '+floattostr(Ratio)+', which should never be lower than 0.');
  43. halt(1);
  44. end;
  45. end;
  46. procedure TCallBackHandler.StartOfFile(Sender: TObject; const AFileName: string);
  47. begin
  48. writeln('Start of file handler hit; filename: '+AFileName);
  49. if (FPerformChecks) and (AFileName='') then
  50. begin
  51. writeln('Archive filename should not be empty.');
  52. halt(1);
  53. end;
  54. end;
  55. procedure TCallBackHandler.DoCreateZipOutputStream(Sender: TObject; var AStream: TStream;
  56. AItem: TFullZipFileEntry);
  57. begin
  58. AStream:=TMemoryStream.Create;
  59. end;
  60. procedure TCallBackHandler.DoDoneOutZipStream(Sender: TObject; var AStream: TStream;
  61. AItem: TFullZipFileEntry);
  62. var
  63. DecompressedContent: string;
  64. begin
  65. //writeln('At end of '+AItem.ArchiveFileName);
  66. AStream.Position:=0;
  67. SetLength(DecompressedContent,Astream.Size);
  68. if AStream.Size>0 then
  69. (AStream as TMemoryStream).Read(DecompressedContent[1], AStream.Size);
  70. if (FPerformChecks) and (DecompressedContent<>OriginalContent) then
  71. begin
  72. FStreamResult:=false;
  73. writeln('TestZipEntries failed: found entry '+AItem.ArchiveFileName+
  74. ' has value ');
  75. writeln('*'+DecompressedContent+'*');
  76. writeln('expected ');
  77. writeln('*'+OriginalContent+'*');
  78. end;
  79. if (FPerformChecks=false) and (ShowContent=true) then
  80. begin
  81. //display only
  82. writeln('TestZipEntries info: found entry '+AItem.ArchiveFileName+
  83. ' has value ');
  84. writeln('*'+DecompressedContent+'*');
  85. end;
  86. Astream.Free;
  87. end;
  88. constructor TCallBackHandler.Create;
  89. begin
  90. FOriginalContent:='A'; //nice short demo content
  91. FStreamResult:=true;
  92. FPerformChecks:=true; //perform verification by default
  93. FShowContent:=true;
  94. end;
  95. function CompareCompressDecompress: boolean;
  96. var
  97. CallBackHandler: TCallBackHandler;
  98. CompressedFile: string;
  99. FileContents: TStringList;
  100. UncompressedFile1: string;
  101. UncompressedFile1Hash: string;
  102. UncompressedFile2: string;
  103. UncompressedFile2Hash: string;
  104. OurZipper: TZipper;
  105. UnZipper: TUnZipper;
  106. begin
  107. result:=true;
  108. UncompressedFile1:=SysUtils.GetTempFileName('', 'UNC');
  109. UncompressedFile2:=SysUtils.GetTempFileName('', 'UNC');
  110. CompressedFile:=SysUtils.GetTempFileName('', 'CC');
  111. FileContents:=TStringList.Create;
  112. OurZipper:=TZipper.Create;
  113. UnZipper:=TUnZipper.Create;
  114. CallBackHandler:=TCallBackHandler.Create;
  115. try
  116. // Set up uncompressed files
  117. FileContents.Add('This is an uncompressed file.');
  118. FileContents.Add('And another line.');
  119. FileContents.SaveToFile(UncompressedFile1);
  120. FileContents.Clear;
  121. FileContents.Add('Have you looked into using fpcup today?');
  122. FileContents.Add('It works nicely with fpc and goes well with a fruity red wine, too.');
  123. FileContents.SaveToFile(UncompressedFile2);
  124. // Remember their content, so we can compare later.
  125. UncompressedFile1Hash:=MD5Print(MD5File(UncompressedFile1, MDDefBufSize));
  126. UncompressedFile2Hash:=MD5Print(MD5File(UncompressedFile2, MDDefBufSize));
  127. // Test zip functionality.
  128. OurZipper.FileName:=CompressedFile;
  129. // Add the files only with their filenames, we don't want to create
  130. // subdirectories:
  131. OurZipper.Entries.AddFileEntry(UncompressedFile1,ExtractFileName(UncompressedFile1));
  132. OurZipper.Entries.AddFileEntry(UncompressedFile2,ExtractFileName(UncompressedFile2));
  133. OurZipper.OnStartFile:[email protected];
  134. OurZipper.OnEndFile:[email protected];
  135. OurZipper.ZipAllFiles;
  136. if not FileExists(CompressedFile) then
  137. begin
  138. writeln('Zip file was not created.');
  139. halt(5);
  140. end;
  141. // Delete original files
  142. {$IFNDEF KEEPTESTFILES}
  143. DeleteFile(UncompressedFile1);
  144. DeleteFile(UncompressedFile2);
  145. {$ENDIF}
  146. // Now unzip
  147. Unzipper.FileName:=CompressedFile;
  148. Unzipper.OutputPath:=ExtractFilePath(UncompressedFile1);
  149. UnZipper.OnStartFile:[email protected];
  150. UnZipper.OnEndFile:[email protected];
  151. Unzipper.Examine;
  152. Unzipper.UnZipAllFiles;
  153. // Now we should have the uncompressed files again
  154. if (not FileExists(UncompressedFile1)) or
  155. (not FileExists(UncompressedFile2)) then
  156. begin
  157. writeln('Unzip failed: could not find decompressed files.');
  158. exit(false);
  159. end;
  160. // Compare hashes
  161. if
  162. (UncompressedFile1Hash<>MD5Print(MD5File(UncompressedFile1, MDDefBufSize)))
  163. or
  164. (UncompressedFile2Hash<>MD5Print(MD5File(UncompressedFile2, MDDefBufSize)))
  165. then
  166. begin
  167. writeln('Unzip failed: uncompressed files are not the same as the originals.');
  168. exit(false);
  169. end;
  170. finally
  171. FileContents.Free;
  172. CallBackHandler.Free;
  173. OurZipper.Free;
  174. UnZipper.Free;
  175. {$IFNDEF KEEPTESTFILES}
  176. try
  177. if FileExists(CompressedFile) then DeleteFile(CompressedFile);
  178. if FileExists(UncompressedFile1) then DeleteFile(UncompressedFile1);
  179. if FileExists(UncompressedFile2) then DeleteFile(UncompressedFile2);
  180. finally
  181. // Ignore errors: OS should eventually clean out temp files anyway
  182. end;
  183. {$ENDIF}
  184. end;
  185. end;
  186. function CompressSmallStreams: boolean;
  187. // Compresses some small streams using default compression and
  188. // no compression (storage)
  189. // Just storing is the best option; compression will enlarge the zip.
  190. // Test verifies that the entries in the zip are not bigger than
  191. // the originals.
  192. var
  193. DestFile: string;
  194. z: TZipper;
  195. zfe: TZipFileEntry;
  196. s: string = 'abcd';
  197. DefaultStream, StoreStream: TStringStream;
  198. begin
  199. result:=true;
  200. DestFile:=SysUtils.GetTempFileName('', 'CS1');
  201. z:=TZipper.Create;
  202. z.FileName:=DestFile;
  203. try
  204. DefaultStream:=TStringStream.Create(s);
  205. StoreStream:=TStringStream.Create(s);
  206. //DefaultStream - compression level = Default
  207. zfe:=z.Entries.AddFileEntry(DefaultStream, 'Compressed');
  208. z.ZipAllFiles;
  209. if (z.Entries[0].Size>zfe.Size) then
  210. begin
  211. result:=false;
  212. writeln('Small stream test default compression failed: compressed size '+
  213. inttostr(z.Entries[0].Size) + ' > original size '+inttostr(zfe.Size));
  214. exit;
  215. end;
  216. finally
  217. DefaultStream.Free;
  218. StoreStream.Free;
  219. z.Free;
  220. end;
  221. {$IFNDEF KEEPTESTFILES}
  222. try
  223. DeleteFile(DestFile);
  224. except
  225. // ignore mess
  226. end;
  227. {$ENDIF}
  228. DestFile:=SysUtils.GetTempFileName('', 'CS2');
  229. z:=TZipper.Create;
  230. z.FileName:=DestFile;
  231. try
  232. DefaultStream:=TStringStream.Create(s);
  233. StoreStream:=TStringStream.Create(s);
  234. //StoreStream - compression level = Store
  235. zfe:=z.Entries.AddFileEntry(StoreStream, 'Uncompressed');
  236. zfe.CompressionLevel:=clnone;
  237. z.ZipAllFiles;
  238. if (z.Entries[0].Size>zfe.Size) then
  239. begin
  240. result:=false;
  241. writeln('Small stream test uncompressed failed: compressed size '+
  242. inttostr(z.Entries[0].Size) + ' > original size '+inttostr(zfe.Size));
  243. exit;
  244. end;
  245. finally
  246. DefaultStream.Free;
  247. StoreStream.Free;
  248. z.Free;
  249. end;
  250. {$IFNDEF KEEPTESTFILES}
  251. try
  252. DeleteFile(DestFile);
  253. except
  254. // ignore mess
  255. end;
  256. {$ENDIF}
  257. //The result can be checked with the command (on Linux):
  258. //unzip -v <DestFile>
  259. //The column Size Shows that compressed files are bigger than source files
  260. end;
  261. function ShowZipFile(ZipFile: string): boolean;
  262. // Reads zip file and lists entries
  263. var
  264. CallBackHandler: TCallBackHandler;
  265. i: integer;
  266. UnZipper: TUnZipper;
  267. UnzipArchiveFiles: TStringList;
  268. begin
  269. result:=true;
  270. UnZipper:=TUnZipper.Create;
  271. CallBackHandler:=TCallBackHandler.Create;
  272. UnzipArchiveFiles:=TStringList.Create;
  273. try
  274. CallBackHandler.PerformChecks:=false; //only display output
  275. UnZipper.FileName:=ZipFile;
  276. Unzipper.Examine;
  277. writeln('ShowZipFile: zip file has '+inttostr(UnZipper.Entries.Count)+' entries');
  278. i:=0;
  279. Unzipper.OnCreateStream:[email protected];
  280. Unzipper.OnDoneStream:[email protected];
  281. while i<Unzipper.Entries.Count do
  282. begin
  283. if CallBackHandler.StreamResult then
  284. begin
  285. UnzipArchiveFiles.Clear;
  286. UnzipArchiveFiles.Add(Unzipper.Entries[i].ArchiveFileName);
  287. Unzipper.UnZipFiles(UnzipArchiveFiles);
  288. // This will kick off the DoCreateOutZipStream/DoDoneOutZipStream handlers
  289. inc(i);
  290. end
  291. else
  292. begin
  293. break; // Handler has reported error; stop loop
  294. end;
  295. end;
  296. finally
  297. Unzipper.Free;
  298. CallBackHandler.Free;
  299. UnzipArchiveFiles.Free;
  300. end;
  301. end;
  302. function TestZipEntries(Entries: qword): boolean;
  303. // Adds Entries amount of zip file entries and reads them
  304. // Starting from 65535 entries, the zip needs to be in zip64 format
  305. var
  306. CallBackHandler: TCallBackHandler;
  307. DestFile: string;
  308. i: qword;
  309. OriginalContent: string = 'A'; //Uncompressed content for zip file entry
  310. ContentStreams: TFPList;
  311. ContentStream: TStringStream;
  312. UnZipper: TUnZipper;
  313. UnzipArchiveFiles: TStringList;
  314. Zipper: TZipper;
  315. begin
  316. result:=true;
  317. DestFile:=SysUtils.GetTempFileName('', 'E'+inttostr(Entries)+'_');
  318. Zipper:=TZipper.Create;
  319. Zipper.FileName:=DestFile;
  320. ContentStreams:=TFPList.Create;
  321. try
  322. i:=0;
  323. while i<Entries do
  324. begin
  325. ContentStream:=TStringStream.Create(OriginalContent);
  326. ContentStreams.Add(ContentStream);
  327. // Start filenames at 1
  328. Zipper.Entries.AddFileEntry(TStringStream(ContentStreams.Items[i]), format('%U',[i+1]));
  329. inc(i);
  330. end;
  331. Zipper.ZipAllFiles;
  332. {
  333. i:=0;
  334. while i<Entries do
  335. begin
  336. ContentStreams.Delete(i);
  337. end;
  338. }
  339. finally
  340. ContentStreams.Free;
  341. Zipper.Free;
  342. end;
  343. UnZipper:=TUnZipper.Create;
  344. CallBackHandler:=TCallBackHandler.Create;
  345. UnzipArchiveFiles:=TStringList.Create;
  346. try
  347. CallBackHandler.OriginalContent:=OriginalContent;
  348. UnZipper.FileName:=DestFile;
  349. Unzipper.Examine;
  350. if (UnZipper.Entries.Count<>Entries) then
  351. begin
  352. result:=false;
  353. writeln('TestZipEntries failed: found '+
  354. inttostr(UnZipper.Entries.Count) + ' entries; expected '+inttostr(Entries));
  355. exit;
  356. end;
  357. i:=0;
  358. Unzipper.OnCreateStream:[email protected];
  359. Unzipper.OnDoneStream:[email protected];
  360. while i<Entries do
  361. begin
  362. if CallBackHandler.StreamResult then
  363. begin
  364. UnzipArchiveFiles.Clear;
  365. UnzipArchiveFiles.Add(Unzipper.Entries[i].ArchiveFileName);
  366. Unzipper.UnZipFiles(UnzipArchiveFiles);
  367. // This will kick off the DoCreateOutZipStream/DoDoneOutZipStream handlers
  368. inc(i);
  369. end
  370. else
  371. begin
  372. break; // Handler has reported error; stop loop
  373. end;
  374. end;
  375. finally
  376. Unzipper.Free;
  377. CallBackHandler.Free;
  378. UnzipArchiveFiles.Free;
  379. end;
  380. {$IFNDEF KEEPTESTFILES}
  381. try
  382. DeleteFile(DestFile);
  383. except
  384. // ignore mess
  385. end;
  386. {$ENDIF}
  387. end;
  388. function TestEmptyZipEntries(Entries: qword): boolean;
  389. // Same as TestZipEntries, except uses empty data:
  390. // useful for testing large number of files
  391. var
  392. CallBackHandler: TCallBackHandler;
  393. DestFile: string;
  394. i: qword;
  395. ContentStreams: TFPList;
  396. ContentStream: TNullStream;
  397. UnZipper: TUnZipper;
  398. UnzipArchiveFiles: TStringList;
  399. Zipper: TZipper;
  400. begin
  401. result:=true;
  402. DestFile:=SysUtils.GetTempFileName('', 'EZ'+inttostr(Entries)+'_');
  403. Zipper:=TZipper.Create;
  404. Zipper.FileName:=DestFile;
  405. ContentStreams:=TFPList.Create;
  406. try
  407. i:=0;
  408. while i<Entries do
  409. begin
  410. ContentStream:=TNullStream.Create;
  411. ContentStreams.Add(ContentStream);
  412. // Start filenames at 1
  413. Zipper.Entries.AddFileEntry(TStringStream(ContentStreams.Items[i]), format('%U',[i+1]));
  414. inc(i);
  415. end;
  416. Zipper.ZipAllFiles;
  417. {
  418. i:=0;
  419. while i<Entries do
  420. begin
  421. ContentStreams.Delete(i);
  422. end;
  423. }
  424. finally
  425. ContentStreams.Free;
  426. Zipper.Free;
  427. end;
  428. UnZipper:=TUnZipper.Create;
  429. UnzipArchiveFiles:=TStringList.Create;
  430. CallBackHandler:=TCallBackHandler.Create;
  431. try
  432. // Use callbacks to dump zip output into the bit bucket
  433. CallBackHandler.PerformChecks:=false;
  434. CallBackHandler.ShowContent:=false;
  435. Unzipper.OnCreateStream:[email protected];
  436. Unzipper.OnDoneStream:[email protected];
  437. UnZipper.FileName:=DestFile;
  438. Unzipper.Examine;
  439. if (UnZipper.Entries.Count<>Entries) then
  440. begin
  441. result:=false;
  442. writeln('TestEmptyZipEntries failed: found '+
  443. inttostr(UnZipper.Entries.Count) + ' entries; expected '+inttostr(Entries));
  444. exit;
  445. end;
  446. i:=0;
  447. while i<Entries do
  448. begin
  449. UnzipArchiveFiles.Clear;
  450. UnzipArchiveFiles.Add(Unzipper.Entries[i].ArchiveFileName);
  451. Unzipper.UnZipFiles(UnzipArchiveFiles);
  452. inc(i);
  453. end;
  454. finally
  455. CallBackHandler.Free;
  456. Unzipper.Free;
  457. UnzipArchiveFiles.Free;
  458. end;
  459. {$IFNDEF KEEPTESTFILES}
  460. try
  461. DeleteFile(DestFile);
  462. except
  463. // ignore mess
  464. end;
  465. {$ENDIF}
  466. end;
  467. function TestLargeFileName: boolean;
  468. // Zips/unzips 259-character filename
  469. var
  470. ArchiveFile: string;
  471. DestFile: string;
  472. s: string = 'a';
  473. DefaultStream: TStringStream;
  474. UnZipper: TUnZipper;
  475. Zipper: TZipper;
  476. begin
  477. result:=true;
  478. ArchiveFile:=StringOfChar('A',259);
  479. DestFile:=SysUtils.GetTempFileName('', 'TL');
  480. Zipper:=TZipper.Create;
  481. Zipper.FileName:=DestFile;
  482. try
  483. DefaultStream:=TStringStream.Create(s);
  484. Zipper.Entries.AddFileEntry(DefaultStream, ArchiveFile);
  485. Zipper.ZipAllFiles;
  486. finally
  487. DefaultStream.Free;
  488. Zipper.Free;
  489. end;
  490. UnZipper:=TUnZipper.Create;
  491. try
  492. UnZipper.FileName:=DestFile;
  493. Unzipper.Examine;
  494. if (Unzipper.Entries[0].ArchiveFileName<>ArchiveFile) then
  495. begin
  496. result:=false;
  497. writeln('TestLargeFileName failed: found filename length '+
  498. inttostr(Length(Unzipper.Entries[0].ArchiveFileName)));
  499. writeln('*'+Unzipper.Entries[0].ArchiveFileName + '*');
  500. writeln('Expected length '+inttostr(Length(ArchiveFile)));
  501. writeln('*'+ArchiveFile+'*');
  502. exit;
  503. end;
  504. finally
  505. Unzipper.Free;
  506. end;
  507. {$IFNDEF KEEPTESTFILES}
  508. try
  509. DeleteFile(DestFile);
  510. except
  511. // ignore mess
  512. end;
  513. {$ENDIF}
  514. end;
  515. function TestLargeZip64: boolean;
  516. // Tests single zip file with large uncompressed content
  517. // which forces it to zip64 format
  518. var
  519. ArchiveFile: string;
  520. Buffer: PChar;
  521. DestFile: string;
  522. ContentStream: TNullStream; //empty contents
  523. UnZipper: TUnZipper;
  524. Zipper: TZipper;
  525. i: int64;
  526. begin
  527. result:=true;
  528. DestFile:=SysUtils.GetTempFileName('', 'LZ');
  529. Zipper:=TZipper.Create;
  530. Zipper.FileName:=DestFile;
  531. ArchiveFile:='HugeString.txt';
  532. ContentStream:=TNullStream.Create;
  533. // About 4Gb; content of 4 bytes+1 added
  534. ContentStream.Size:=(1+$FFFFFFFF);
  535. ContentStream.Position:=0;
  536. writeln('Buffer created');
  537. try
  538. Zipper.Entries.AddFileEntry(ContentStream, ArchiveFile);
  539. writeln('entry added');
  540. Zipper.ZipAllFiles;
  541. finally
  542. ContentStream.Free;
  543. Zipper.Free;
  544. end;
  545. UnZipper:=TUnZipper.Create;
  546. try
  547. UnZipper.FileName:=DestFile;
  548. Unzipper.Examine;
  549. if (UnZipper.Entries.Count<>1) then
  550. begin
  551. result:=false;
  552. writeln('TestLargeZip64 failed: found '+
  553. inttostr(UnZipper.Entries.Count) + ' entries; expected 1');
  554. exit;
  555. end;
  556. if (Unzipper.Entries[0].ArchiveFileName<>ArchiveFile) then
  557. begin
  558. result:=false;
  559. writeln('TestLargeZip64 failed: found filename length '+
  560. inttostr(Length(Unzipper.Entries[0].ArchiveFileName)));
  561. writeln('*'+Unzipper.Entries[0].ArchiveFileName + '*');
  562. writeln('Expected length '+inttostr(Length(ArchiveFile)));
  563. writeln('*'+ArchiveFile+'*');
  564. exit;
  565. end;
  566. finally
  567. Unzipper.Free;
  568. end;
  569. {$IFNDEF KEEPTESTFILES}
  570. try
  571. DeleteFile(DestFile);
  572. except
  573. // ignore mess
  574. end;
  575. {$ENDIF}
  576. end;
  577. var
  578. code: cardinal; //test result code: 0 for success
  579. begin
  580. code:=0;
  581. try
  582. if FileExists(ParamStr(1)) then
  583. begin
  584. writeln('');
  585. writeln('Started investigating file '+ParamStr(1));
  586. ShowZipFile(ParamStr(1));
  587. writeln('Finished investigating file '+ParamStr(1));
  588. writeln('');
  589. end;
  590. writeln('CompareCompressDecompress started');
  591. if not(CompareCompressDecompress) then code:=code+2; //1 already taken by callback handler
  592. writeln('CompareCompressDecompress finished');
  593. writeln('');
  594. writeln('CompressSmallStreams started');
  595. if not(CompressSmallStreams) then code:=code+4;
  596. writeln('CompressSmallStreams finished');
  597. writeln('');
  598. writeln('TestZipEntries(2) started');
  599. if not(TestZipEntries(2)) then code:=code+8;
  600. writeln('TestZipEntries(2) finished');
  601. writeln('');
  602. writeln('TestLargeFileName started');
  603. if not(TestLargeFileName) then code:=code+16;
  604. writeln('TestLargeFileName finished');
  605. writeln('');
  606. writeln('TestEmptyZipEntries(10) started');
  607. // Run testemptyzipentries with a small number to test the test itself... as
  608. // well as zip structure generated with empty files.
  609. if not(TestEmptyZipEntries(10)) then code:=code+32;
  610. writeln('TestEmptyZipEntries(10) finished');
  611. writeln('');
  612. writeln('TestEmptyZipEntries(65537) started');
  613. writeln('(note: this will take a long time)');
  614. {Note: tested tools with this file:
  615. - info-zip unzip 6.0
  616. - Ionic's DotNetZip library unzip.exe utility verison 1.9.1.8 works
  617. - 7zip's 7za 9.22 beta works.
  618. }
  619. if not(TestEmptyZipEntries(65537)) then code:=code+32;
  620. writeln('TestEmptyZipEntries(65537) finished');
  621. writeln('');
  622. { This test will take a very long time as it tries to zip a 4Gb memory block.
  623. It is therefore commented out by default }
  624. {
  625. writeln('TestLargeZip64 - started');
  626. if not(TestLargeZip64) then code:=code+thefollowingstatuscode;
  627. writeln('TestLargeZip64 format - finished');
  628. writeln('');
  629. }
  630. except
  631. on E: Exception do
  632. begin
  633. writeln('');
  634. writeln('Exception: ');
  635. writeln(E.Message);
  636. writeln('');
  637. end;
  638. end;
  639. if code=0 then
  640. writeln('Basic zip/unzip tests passed: code '+inttostr(code))
  641. else
  642. writeln('Basic zip/unzip tests failed: code '+inttostr(code));
  643. Halt(code);
  644. end.