------------------------->  GNU Sather - sourcefile  <-------------------------
-- Copyright (C) 1995 by International Computer Science Institute            --
-- This file is part of the GNU Sather library. It is free software; you may --
-- redistribute  and/or modify it under the terms of the GNU Library General --
-- Public  License (LGPL)  as published  by the  Free  Software  Foundation; --
-- either version 2 of the license, or (at your option) any later version.   --
-- This  library  is distributed  in the  hope that it will  be  useful, but --
-- WITHOUT ANY WARRANTY without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See Doc/LGPL for more details.       --
-- The license text is also available from:  Free Software Foundation, Inc., --
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                     --
-------------->  Please email comments to <bug-sather@gnu.org>  <--------------

-- Test class for bags
-- Author: Benedict A. Gomes <gomes@samosa.ICSI.Berkeley.EDU>

class BAG_TEST is
   -- Test of a creatable read/write bag
   include TEST;

   main is
      test_int_bag;
      test_flt_bag;
      test_int_vbag;
      test_flt_vbag;
   end;
   
   test_int_bag is
      elts:ARRAY{INT} := |0,1,2,3,4,5,6,7,8,9,10,11|;
      bags0 ::= #BAG{INT};
      bags1 ::= #BAG{INT}(|0,2,2,4,6,6|);
      bags2 ::= #BAG{INT}(|1,2,3,4,5,6,7,8,9,9,10,10,10|);
      BAG_TEST{INT}::test_bag_readonly(bags0,bags1,bags2,elts);
      BAG_TEST{INT}::test_bag_reference(bags0,bags1,bags2,elts);
   end;      
   
   test_flt_bag is
      eltsflt:ARRAY{FLT} := |0.0,1.0,2.0,3.0,4.0,5.0,6.0,
			     7.0,8.0,9.0,10.0,11.0|;
      bags0 ::= #BAG{FLT};
      bags1 ::= #BAG{FLT}(|0.0,2.0,2.0,4.0,6.0,6.0|);
      bags2 ::= #BAG{FLT}(|1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,9.0,10.0,
			   10.0,10.0|);
      BAG_TEST{FLT}::test_bag_readonly(bags0,bags1,bags2,eltsflt);
      BAG_TEST{FLT}::test_bag_reference(bags0,bags1,bags2,eltsflt);
   end;
   
   test_int_vbag is
      elts:ARRAY{INT} := |0,1,2,3,4,5,6,7,8,9,10,11|;
      bags0 ::= #VBAG{INT};
      bags1 ::= #VBAG{INT}(|0,2,2,4,6,6|);
      bags2 ::= #VBAG{INT}(|1,2,3,4,5,6,7,8,9,9,10,10,10|);
      BAG_TEST{INT}::test_bag_readonly(bags0,bags1,bags2,elts);
   end;
   
   test_flt_vbag is
      eltsflt:ARRAY{FLT} := |0.0,1.0,2.0,3.0,4.0,5.0,6.0,
			     7.0,8.0,9.0,10.0,11.0|;
      bags0 ::= #VBAG{FLT};
      bags1 ::= #VBAG{FLT}(|0.0,2.0,2.0,4.0,6.0,6.0|);
      bags2 ::= #VBAG{FLT}(|1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,9.0,10.0,
			   10.0,10.0|);
      BAG_TEST{FLT}::test_bag_readonly(bags0,bags1,bags2,eltsflt);
   end;
   
   
end;
-------------------------------------------------------------------
class BAG_TEST{T} is
   -- Test of bags with elemetns of type 't'
   include TEST;
   
   test_setlike_bags(bag0,bag1,bag3:$RO_BAG{T},e:ARRAY{T}) is
      -- Tests of bags that look like sets. The same tests
      -- can be run on sets and the results should be the same
      -- bag0 must be empty
      -- bag1 must contain {0,2,4,6}
      -- bag3 must contain {1,2,3,4,5,6,7,8,9,10}
      
      tpstr ::= SYS::str_for_tp(SYS::tp(bag1));
      class_name("setlike BAG:"+tpstr);
      
      bag2 ::= bag1.copy;
      #OUT+"Bag0="+bag0.str
	    +"\nBag1="+bag1.str
	    +"\nBag3="+bag3.str+"\n";
      
      test("concat",
	   eq(bag1.concat(bag2),
	      bag1.add(e[0]).add(e[2]).add(e[4]).add(e[6])),
	   true);
      
      test("union",
	   eq(bag3.union(bag2),bag3.add(e[0])),
	   true);
      test("intersection",
	   eq(bag3.intersection(bag2),
	      bag2.delete(e[0])),
	   true);
      finish;
   end;
   
   test_bag_readonly(bag0,bag1,bag3:$RO_BAG{T},e:ARRAY{T}) is
      -- Various tests of the read-only/value class routines
      -- 'e' contains the elements of the bags, referrered to by
      -- the index below
      
      -- bag0 must be empty
      -- bag1 must contain {0,2,2,4,6,6}
      -- bag3 must contain {1,2,3,4,5,6,7,8,9,9,10,10,10}

      tpstr ::= SYS::str_for_tp(SYS::tp(bag1));
      class_name("readonly BAG:"+tpstr);
      
      bag2 ::= bag1.copy;
      #OUT+"Bag0="+bag0.str
	    +"\nBag1="+bag1.str
	    +"\nBag3="+bag3.str+"\n";
      
      test("size",bag0.size,0);
      test("size",bag1.size,6);
      test("is_empty",bag0.is_empty,true);
      test("is_empty",bag1.is_empty,false);
      test("bag1.has(0)",bag1.has(e[0]),true);
      test("bag1.has(1)",bag1.has(e[1]),false);
      test("bag1.count(2)",bag1.count(e[1]),0);
      test("bag1.count(2)",bag1.count(e[2]),2);
      test("bag1.count(0)",bag1.count(e[0]),1);
      test("bag1 equals bag2",eq(bag1,bag2),true);
      test("bag1.n_unique",bag1.n_unique,4);
      bag1_copy ::= bag1.copy;
      nun ::= 0;  
      loop d ::= bag1.unique!; 
	 nun := nun + 1; bag1_copy := bag1_copy.delete_all(d); 
      end;
      test("bag1.unique!",nun,4);
      test("bag1_copy.size",bag1_copy.size,0);
      
      test("bag1.is_subset_of(bag2)",bag1.is_subset_of(bag2),true);
      test("bag1.concat(bag2)",
	   eq(bag1.concat(bag2),
	      bag1.add(e[0]).add(e[2]).add(e[2]).add(e[4]).add(e[6]).add(e[6]))
	   ,true);
      test("bag1.union(bag2)",  eq(bag1.union(bag2),bag1),  true);
      test("bag1.union(bag3)",  
	   eq(bag1.union(bag3),
	      bag3.add(e[0]).add(e[2]).add(e[6])),
	   true);
      test("bag1.intersection(bag3)",
	   eq(bag1.intersection(bag3),
	      bag2.delete(e[0]).delete(e[2]).delete(e[6])),
	   true);
      finish;
   end;

   test_bag_reference(bag0,bag1,bag2:$BAG{T},e:ARRAY{T}) is
      -- Various tests of the read-only/value class routines
      -- bag0 must be empty
      -- bag1 must contain {0,1,2,3,4,4}
      -- bag2 must contain {0,  2,3,    ,5}

      tpstr ::= SYS::str_for_tp(SYS::tp(bag1));
      class_name("modifying SET:"+tpstr);
      
      #OUT+"Bag0="+bag0.str +"\nBag1="+bag1.str+"\nBag2="+bag2.str+"\n";

      -- Use the readonly version to verify the result
      bag3 ::= bag1.copy;
      bag3.add(e[0]);
      bag3.add(e[1]);
      bag3.add(e[2]);
      bag3.delete_all(e[4]);
      bag3.delete(e[3]);

      test("add,delete",
	   eq(bag3,
	      bag1.add(e[0]).add(e[1]).add(e[2])
	      .delete_all(e[4]).delete(e[3])),
	   true);
      
      bag5 ::= bag1.copy;
      bag5.to_concat(bag2);
      test("to_concat",eq(bag5, bag1.concat(bag2)), true);

      bag6 ::= bag1.copy;
      bag6.to_union(bag2);
      test("to_union",eq(bag6,bag1.union(bag2)),true);
      
      bag7 ::= bag1.copy;
      bag7.to_intersection(bag2);
      test("to_intersection",eq(bag7,bag1.intersection(bag2)),true);

      bag8 ::= bag1.copy;
      bag8.clear;
      test("clear",eq(bag7,bag1.intersection(bag2)),true);
      finish;
   end;

   eq(m1,m2:$RO_BAG{T}):BOOL is
      #OUT+"First="+m1.str+"\nSecond="+m2.str+"\n";
      return m1.equals(m2);
   end;      
   
end;
-------------------------------------------------------------------
