import java.util.Random;
import java.io.PrintStream;


import mySet.*;


public class TestSets
{
    private final int MaxSetElement = 100;

    private Random rgen;
    
    private boolean checkSetContents (Set s, boolean[] expectedMembers)
    {
	int expectedSize = 0;
	int discoveredSize = 0;
	boolean result = true;

	for (int i = 0; i < MaxSetElement; i++)
	  {
	    if (expectedMembers[i])
	      {
		expectedSize++;
		if (s.member(i))
		  {
		    discoveredSize++;
		  }
		else
		  {
		    System.out.println ("Set is missing expected element: " + i);
		    result = false;
		  }
	      }
	    else
	      {
		if (s.member(i))
		  {
		    discoveredSize++;
		    System.out.println ("Set contains unexpected element: " + i);
		    result = false;
		  }
	      }
	  }
	
	if (expectedSize != discoveredSize)
	  {
	    System.out.println ("Number of elements in set: "
				+ discoveredSize +
				" does not match expected number: "
				+ expectedSize);
	    result = false;
	  }
	
	if (s.extent() != discoveredSize)
	    {
		System.out.println (
			"Number of elements in set: " + discoveredSize
			+  " does not match reported number (extent): "
			+ s.extent());
		result = false;
	    }
	return result;
    }
    

    private void generateSet (int numElements, Set s, boolean[] expected)
    {
	int[] elements = new int[MaxSetElement];
  

	for (int i = 0; i < MaxSetElement; i++)
	    {
		elements[i] = i;
		expected[i] = false;
	    }
  

	// Now scramble the ordering of the elements array
	for (int i = 0; i < MaxSetElement; i++)
	    {
		int j = -1;
		while (j < 0) j = (rgen.nextInt()) % MaxSetElement;
		int t = elements[i];
		elements[i] = elements[j];
		elements[j] = t;
	    }

	// Insert the first numElements values into s
	s.clear();
	for (int i = 0; i < numElements; i++)
	    {
		s.add(elements[i]);
		expected[elements[i]] = true;
	    }
    }

  
  
    private boolean testSet (Set s, boolean[] expected)
    {

      Set s1 = (Set)s.clone();

      // Check set for internal consistency
  
      if (!checkSetContents(s, expected))
	  return false;
      if (!checkSetContents(s1, expected))
	  return false;
  
      
      // Axiom 1: After s.clear(), s.extent()==0
      boolean[] noneExpected = new boolean[MaxSetElement];
      for (int k = 0; k < MaxSetElement; ++k) noneExpected[k] = false;
      s1.clear();
      if (!checkSetContents(s1, noneExpected))
	  return false;

      // Axiom 2: adding a member X ...

      s1 = (Set)s.clone();
      int x = -1;
      while (x < 0) x = rgen.nextInt() % MaxSetElement;
      if (s1.member(x))
	  {
	      // ...that is already in s results in no change to s
	      s1.add(x);
	      if ((!checkSetContents(s1, expected))
		  || (s.extent() != s1.extent()))
		  return false;
	  }
      else
	  {
	      // ...that is not in s results in a new member and larger extent
	      s1.add(x);
	      boolean[] moreExpected = new boolean[MaxSetElement];
	      for (int ii = 0; ii < MaxSetElement; ii++)
		  moreExpected[ii] = expected[ii];
      
	      moreExpected[x] = true;
	      if ((!checkSetContents(s1, moreExpected))
		  || (s.extent() != s1.extent()-1))
		  return false;
	  }
      return true;
      
    }


    public TestSets()
    {
	rgen = new Random();
    }
    

    public void runTest() 
    {
	boolean[] expected = new boolean[MaxSetElement];

	boolean ok = true;
	System.out.println ("\n\nTesting  sets");
	for (int testSize = 0; ok && (testSize < MaxSetElement);
	     testSize = 2*testSize + 1)
	    {
		Set s = new Set();
		System.out.println ("Size: " + testSize);
		generateSet (testSize, s, expected);
		ok = testSet (s, expected);
	    }


	if (!ok)
	    System.out.println ("Errors detected during execution");
    }

    public static void main (String[] args)
    {
	TestSets ts = new TestSets();
	ts.runTest();
    }


}

