with Integer_Character_Hashed_Maps;  use Integer_Character_Hashed_Maps;
with Ada.Text_IO;  use Ada.Text_IO;
with Ada.Numerics.Discrete_Random;

procedure Test_Hashed_Maps is

   subtype Integer_Subtype is Integer range 1 .. 1000;

   package Random_Keys is
      new Ada.Numerics.Discrete_Random (Integer_Subtype);

   GK : Random_Keys.Generator;

   subtype Character_Subtype is
     Character range Character'Succ (' ') .. '~';

   package Random_Elements is
       new Ada.Numerics.Discrete_Random (Character_Subtype);

   GE : Random_Elements.Generator;

   use Random_Keys, Random_Elements;

   M, M2 : Container_Type;

   K : Integer;
   E : Character;

   I, J : Iterator_Type;
   B : Boolean;

   N : Natural;

begin

   Reset (GK);
   Reset (GE);

   pragma Assert (First (M) = Back (M));
   pragma Assert (Length (M) = 0);

   pragma Assert (M = M2);

   M2 := M;
   pragma Assert (M = M2);

   Assign (Target => M2, Source => M);
   pragma Assert (M = M2);

   E := Random (GE);

   Insert (M, 42, E, I, B);
   pragma Assert (Length (M) = 1);
   pragma Assert (B);
   pragma Assert (Key (I) = 42);
   pragma Assert (Element (I) = E);
   pragma Assert (I = First (M));
   pragma Assert (Succ (M, I) = Back (M));

   M2 := M;
   pragma Assert (M = M2);

   Assign (Target => M2, Source => M);
   pragma Assert (M = M2);

   J := Find (M, Key => 42);
   pragma Assert (J /= Back (M));
   pragma Assert (Key (J) = 42);
   pragma Assert (Element (J) = E);

   M2 := M;
   pragma Assert (M = M2);

   Assign (Target => M2, Source => M);
   pragma Assert (M = M2);

   Put_Line ("inserting");

   loop

      N := Length (M);

      exit when N > 900;

      K := Random (GK);
      E := Random (GE);

      Insert (M, K, E, I, B);

      pragma Assert (Key (I) = K);

      J := Find (M, K);
      pragma Assert (J /= Back (M));
      pragma Assert (Key (J) = K);

      if B then
         pragma Assert (Length (M) = N + 1);
         pragma Assert (Element (J) = E);
         null;
      else
         pragma Assert (Length (M) = N);
         null;
      end if;

      M2 := M;
      pragma Assert (M = M2);

      Assign (Target => M2, Source => M);
      pragma Assert (M = M2);

   end loop;

   Put_Line ("deleting");

   while not Is_Empty (M) loop

      I := First (M);

      for Index in 1 .. Random (GK) mod Length (M) loop
         Increment (M, I);
      end loop;

      pragma Assert (I /= Back (M));

      K := Key (I);

      Delete (M, I);

      pragma Assert (not Is_In (K, M));

      M2 := M;
      pragma Assert (M = M2);

      Assign (Target => M2, Source => M);
      pragma Assert (M = M2);

   end loop;

end Test_Hashed_Maps;


