1 ----------------------------------------------------------------
   2 --  ZLib for Ada thick binding.                               --
   3 --                                                            --
   4 --  Copyright (C) 2002-2003 Dmitriy Anisimkov                 --
   5 --                                                            --
   6 --  Open source license information is in the zlib.ads file.  --
   7 ----------------------------------------------------------------
   8 
   9 --  $Id: test.adb,v 1.17 2003/08/12 12:13:30 vagul Exp $
  10 
  11 --  The program has a few aims.
  12 --  1. Test ZLib.Ada95 thick binding functionality.
  13 --  2. Show the example of use main functionality of the ZLib.Ada95 binding.
  14 --  3. Build this program automatically compile all ZLib.Ada95 packages under
  15 --     GNAT Ada95 compiler.
  16 
  17 with ZLib.Streams;
  18 with Ada.Streams.Stream_IO;
  19 with Ada.Numerics.Discrete_Random;
  20 
  21 with Ada.Text_IO;
  22 
  23 with Ada.Calendar;
  24 
  25 procedure Test is
  26 
  27    use Ada.Streams;
  28    use Stream_IO;
  29 
  30    ------------------------------------
  31    --  Test configuration parameters --
  32    ------------------------------------
  33 
  34    File_Size   : Count   := 100_000;
  35    Continuous  : constant Boolean := False;
  36 
  37    Header      : constant ZLib.Header_Type := ZLib.Default;
  38                                               --  ZLib.None;
  39                                               --  ZLib.Auto;
  40                                               --  ZLib.GZip;
  41    --  Do not use Header other then Default in ZLib versions 1.1.4
  42    --  and older.
  43 
  44    Strategy    : constant ZLib.Strategy_Type := ZLib.Default_Strategy;
  45    Init_Random : constant := 10;
  46 
  47    -- End --
  48 
  49    In_File_Name  : constant String := "testzlib.in";
  50    --  Name of the input file
  51 
  52    Z_File_Name   : constant String := "testzlib.zlb";
  53    --  Name of the compressed file.
  54 
  55    Out_File_Name : constant String := "testzlib.out";
  56    --  Name of the decompressed file.
  57 
  58    File_In   : File_Type;
  59    File_Out  : File_Type;
  60    File_Back : File_Type;
  61    File_Z    : ZLib.Streams.Stream_Type;
  62 
  63    Filter : ZLib.Filter_Type;
  64 
  65    Time_Stamp : Ada.Calendar.Time;
  66 
  67    procedure Generate_File;
  68    --  Generate file of spetsified size with some random data.
  69    --  The random data is repeatable, for the good compression.
  70 
  71    procedure Compare_Streams
  72      (Left, Right : in out Root_Stream_Type'Class);
  73    --  The procedure compearing data in 2 streams.
  74    --  It is for compare data before and after compression/decompression.
  75 
  76    procedure Compare_Files (Left, Right : String);
  77    --  Compare files. Based on the Compare_Streams.
  78 
  79    procedure Copy_Streams
  80      (Source, Target : in out Root_Stream_Type'Class;
  81       Buffer_Size    : in     Stream_Element_Offset := 1024);
  82    --  Copying data from one stream to another. It is for test stream
  83    --  interface of the library.
  84 
  85    procedure Data_In
  86      (Item : out Stream_Element_Array;
  87       Last : out Stream_Element_Offset);
  88    --  this procedure is for generic instantiation of
  89    --  ZLib.Generic_Translate.
  90    --  reading data from the File_In.
  91 
  92    procedure Data_Out (Item : in Stream_Element_Array);
  93    --  this procedure is for generic instantiation of
  94    --  ZLib.Generic_Translate.
  95    --  writing data to the File_Out.
  96 
  97    procedure Stamp;
  98    --  Store the timestamp to the local variable.
  99 
 100    procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count);
 101    --  Print the time statistic with the message.
 102 
 103    procedure Translate is new ZLib.Generic_Translate
 104                                 (Data_In  => Data_In,
 105                                  Data_Out => Data_Out);
 106    --  This procedure is moving data from File_In to File_Out
 107    --  with compression or decompression, depend on initialization of
 108    --  Filter parameter.
 109 
 110    -------------------
 111    -- Compare_Files --
 112    -------------------
 113 
 114    procedure Compare_Files (Left, Right : String) is
 115       Left_File, Right_File : File_Type;
 116    begin
 117       Open (Left_File, In_File, Left);
 118       Open (Right_File, In_File, Right);
 119       Compare_Streams (Stream (Left_File).all, Stream (Right_File).all);
 120       Close (Left_File);
 121       Close (Right_File);
 122    end Compare_Files;
 123 
 124    ---------------------
 125    -- Compare_Streams --
 126    ---------------------
 127 
 128    procedure Compare_Streams
 129      (Left, Right : in out Ada.Streams.Root_Stream_Type'Class)
 130    is
 131       Left_Buffer, Right_Buffer : Stream_Element_Array (0 .. 16#FFF#);
 132       Left_Last, Right_Last : Stream_Element_Offset;
 133    begin
 134       loop
 135          Read (Left, Left_Buffer, Left_Last);
 136          Read (Right, Right_Buffer, Right_Last);
 137 
 138          if Left_Last /= Right_Last then
 139             Ada.Text_IO.Put_Line ("Compare error :"
 140               & Stream_Element_Offset'Image (Left_Last)
 141               & " /= "
 142               & Stream_Element_Offset'Image (Right_Last));
 143 
 144             raise Constraint_Error;
 145 
 146          elsif Left_Buffer (0 .. Left_Last)
 147                /= Right_Buffer (0 .. Right_Last)
 148          then
 149             Ada.Text_IO.Put_Line ("ERROR: IN and OUT files is not equal.");
 150             raise Constraint_Error;
 151 
 152          end if;
 153 
 154          exit when Left_Last < Left_Buffer'Last;
 155       end loop;
 156    end Compare_Streams;
 157 
 158    ------------------
 159    -- Copy_Streams --
 160    ------------------
 161 
 162    procedure Copy_Streams
 163      (Source, Target : in out Ada.Streams.Root_Stream_Type'Class;
 164       Buffer_Size    : in     Stream_Element_Offset := 1024)
 165    is
 166       Buffer : Stream_Element_Array (1 .. Buffer_Size);
 167       Last   : Stream_Element_Offset;
 168    begin
 169       loop
 170          Read  (Source, Buffer, Last);
 171          Write (Target, Buffer (1 .. Last));
 172 
 173          exit when Last < Buffer'Last;
 174       end loop;
 175    end Copy_Streams;
 176 
 177    -------------
 178    -- Data_In --
 179    -------------
 180 
 181    procedure Data_In
 182      (Item : out Stream_Element_Array;
 183       Last : out Stream_Element_Offset) is
 184    begin
 185       Read (File_In, Item, Last);
 186    end Data_In;
 187 
 188    --------------
 189    -- Data_Out --
 190    --------------
 191 
 192    procedure Data_Out (Item : in Stream_Element_Array) is
 193    begin
 194       Write (File_Out, Item);
 195    end Data_Out;
 196 
 197    -------------------
 198    -- Generate_File --
 199    -------------------
 200 
 201    procedure Generate_File is
 202       subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#;
 203 
 204       package Random_Elements is
 205          new Ada.Numerics.Discrete_Random (Visible_Symbols);
 206 
 207       Gen    : Random_Elements.Generator;
 208       Buffer : Stream_Element_Array := (1 .. 77 => 16#20#) & 10;
 209 
 210       Buffer_Count : constant Count := File_Size / Buffer'Length;
 211       --  Number of same buffers in the packet.
 212 
 213       Density : constant Count := 30; --  from 0 to Buffer'Length - 2;
 214 
 215       procedure Fill_Buffer (J, D : in Count);
 216       --  Change the part of the buffer.
 217 
 218       -----------------
 219       -- Fill_Buffer --
 220       -----------------
 221 
 222       procedure Fill_Buffer (J, D : in Count) is
 223       begin
 224          for K in 0 .. D loop
 225             Buffer
 226               (Stream_Element_Offset ((J + K) mod (Buffer'Length - 1) + 1))
 227              := Random_Elements.Random (Gen);
 228 
 229          end loop;
 230       end Fill_Buffer;
 231 
 232    begin
 233       Random_Elements.Reset (Gen, Init_Random);
 234 
 235       Create (File_In, Out_File, In_File_Name);
 236 
 237       Fill_Buffer (1, Buffer'Length - 2);
 238 
 239       for J in 1 .. Buffer_Count loop
 240          Write (File_In, Buffer);
 241 
 242          Fill_Buffer (J, Density);
 243       end loop;
 244 
 245       --  fill remain size.
 246 
 247       Write
 248         (File_In,
 249          Buffer
 250            (1 .. Stream_Element_Offset
 251                    (File_Size - Buffer'Length * Buffer_Count)));
 252 
 253       Flush (File_In);
 254       Close (File_In);
 255    end Generate_File;
 256 
 257    ---------------------
 258    -- Print_Statistic --
 259    ---------------------
 260 
 261    procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count) is
 262       use Ada.Calendar;
 263       use Ada.Text_IO;
 264 
 265       package Count_IO is new Integer_IO (ZLib.Count);
 266 
 267       Curr_Dur : Duration := Clock - Time_Stamp;
 268    begin
 269       Put (Msg);
 270 
 271       Set_Col (20);
 272       Ada.Text_IO.Put ("size =");
 273 
 274       Count_IO.Put
 275         (Data_Size,
 276          Width => Stream_IO.Count'Image (File_Size)'Length);
 277 
 278       Put_Line (" duration =" & Duration'Image (Curr_Dur));
 279    end Print_Statistic;
 280 
 281    -----------
 282    -- Stamp --
 283    -----------
 284 
 285    procedure Stamp is
 286    begin
 287       Time_Stamp := Ada.Calendar.Clock;
 288    end Stamp;
 289 
 290 begin
 291    Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version);
 292 
 293    loop
 294       Generate_File;
 295 
 296       for Level in ZLib.Compression_Level'Range loop
 297 
 298          Ada.Text_IO.Put_Line ("Level ="
 299             & ZLib.Compression_Level'Image (Level));
 300 
 301          --  Test generic interface.
 302          Open   (File_In, In_File, In_File_Name);
 303          Create (File_Out, Out_File, Z_File_Name);
 304 
 305          Stamp;
 306 
 307          --  Deflate using generic instantiation.
 308 
 309          ZLib.Deflate_Init
 310                (Filter   => Filter,
 311                 Level    => Level,
 312                 Strategy => Strategy,
 313                 Header   => Header);
 314 
 315          Translate (Filter);
 316          Print_Statistic ("Generic compress", ZLib.Total_Out (Filter));
 317          ZLib.Close (Filter);
 318 
 319          Close (File_In);
 320          Close (File_Out);
 321 
 322          Open   (File_In, In_File, Z_File_Name);
 323          Create (File_Out, Out_File, Out_File_Name);
 324 
 325          Stamp;
 326 
 327          --  Inflate using generic instantiation.
 328 
 329          ZLib.Inflate_Init (Filter, Header => Header);
 330 
 331          Translate (Filter);
 332          Print_Statistic ("Generic decompress", ZLib.Total_Out (Filter));
 333 
 334          ZLib.Close (Filter);
 335 
 336          Close (File_In);
 337          Close (File_Out);
 338 
 339          Compare_Files (In_File_Name, Out_File_Name);
 340 
 341          --  Test stream interface.
 342 
 343          --  Compress to the back stream.
 344 
 345          Open   (File_In, In_File, In_File_Name);
 346          Create (File_Back, Out_File, Z_File_Name);
 347 
 348          Stamp;
 349 
 350          ZLib.Streams.Create
 351            (Stream          => File_Z,
 352             Mode            => ZLib.Streams.Out_Stream,
 353             Back            => ZLib.Streams.Stream_Access
 354                                  (Stream (File_Back)),
 355             Back_Compressed => True,
 356             Level           => Level,
 357             Strategy        => Strategy,
 358             Header          => Header);
 359 
 360          Copy_Streams
 361            (Source => Stream (File_In).all,
 362             Target => File_Z);
 363 
 364          --  Flushing internal buffers to the back stream.
 365 
 366          ZLib.Streams.Flush (File_Z, ZLib.Finish);
 367 
 368          Print_Statistic ("Write compress",
 369                           ZLib.Streams.Write_Total_Out (File_Z));
 370 
 371          ZLib.Streams.Close (File_Z);
 372 
 373          Close (File_In);
 374          Close (File_Back);
 375 
 376          --  Compare reading from original file and from
 377          --  decompression stream.
 378 
 379          Open (File_In,   In_File, In_File_Name);
 380          Open (File_Back, In_File, Z_File_Name);
 381 
 382          ZLib.Streams.Create
 383            (Stream          => File_Z,
 384             Mode            => ZLib.Streams.In_Stream,
 385             Back            => ZLib.Streams.Stream_Access
 386                                  (Stream (File_Back)),
 387             Back_Compressed => True,
 388             Header          => Header);
 389 
 390          Stamp;
 391          Compare_Streams (Stream (File_In).all, File_Z);
 392 
 393          Print_Statistic ("Read decompress",
 394                           ZLib.Streams.Read_Total_Out (File_Z));
 395 
 396          ZLib.Streams.Close (File_Z);
 397          Close (File_In);
 398          Close (File_Back);
 399 
 400          --  Compress by reading from compression stream.
 401 
 402          Open (File_Back, In_File, In_File_Name);
 403          Create (File_Out, Out_File, Z_File_Name);
 404 
 405          ZLib.Streams.Create
 406            (Stream          => File_Z,
 407             Mode            => ZLib.Streams.In_Stream,
 408             Back            => ZLib.Streams.Stream_Access
 409                                  (Stream (File_Back)),
 410             Back_Compressed => False,
 411             Level           => Level,
 412             Strategy        => Strategy,
 413             Header          => Header);
 414 
 415          Stamp;
 416          Copy_Streams
 417            (Source => File_Z,
 418             Target => Stream (File_Out).all);
 419 
 420          Print_Statistic ("Read compress",
 421                           ZLib.Streams.Read_Total_Out (File_Z));
 422 
 423          ZLib.Streams.Close (File_Z);
 424 
 425          Close (File_Out);
 426          Close (File_Back);
 427 
 428          --  Decompress to decompression stream.
 429 
 430          Open   (File_In,   In_File, Z_File_Name);
 431          Create (File_Back, Out_File, Out_File_Name);
 432 
 433          ZLib.Streams.Create
 434            (Stream          => File_Z,
 435             Mode            => ZLib.Streams.Out_Stream,
 436             Back            => ZLib.Streams.Stream_Access
 437                                  (Stream (File_Back)),
 438             Back_Compressed => False,
 439             Header          => Header);
 440 
 441          Stamp;
 442 
 443          Copy_Streams
 444            (Source => Stream (File_In).all,
 445             Target => File_Z);
 446 
 447          Print_Statistic ("Write decompress",
 448                           ZLib.Streams.Write_Total_Out (File_Z));
 449 
 450          ZLib.Streams.Close (File_Z);
 451          Close (File_In);
 452          Close (File_Back);
 453 
 454          Compare_Files (In_File_Name, Out_File_Name);
 455       end loop;
 456 
 457       Ada.Text_IO.Put_Line (Count'Image (File_Size) & " Ok.");
 458 
 459       exit when not Continuous;
 460 
 461       File_Size := File_Size + 1;
 462    end loop;
 463 end Test;