/*  TestCases.java
 *  Geoff Oakham (oakhamg@cs)
 *  Oct 26, 2001
 */

/* 148.a2 tester, Nick Chang */

import java.lang.reflect.Modifier;
import java.io.*;
import java.util.*;
import java.lang.reflect.*;

class TestCases {
  
    static public int TOTAL_TESTS = 71;
    static public int FREE_MARKS = 0;
    private Logger logger;
    private StructureChecker structureChecker;
  
    public TestCases(Logger logger) {
 this.logger = logger;
 structureChecker= new StructureChecker(logger);
    }
  
    /** Performs test number "testNumber" and returns true if the testcase
     * succeeds.  The caller takes responsibility for any stray exceptions
     * thrown during testing.  These exceptions will be recorded and logged
     * appropriately (ie, as failed testcases.)  A test case that excercises
     * code that's supposed to throw exceptions, should catch those
     * exceptions and report their testcases as 'passed'.
     *
     * NOTE: it is important the caller receive all thrown threading-related
     * exceptions, including 'threaddeath' and 'interupt'.  Should you decide
     * to catch stray exceptions yourself please keep this in mind.  Please
     * also consider modifying the upstream code to meet your needs instead.
     *
     * Preconditions: 0 <= testNumber < TOTAL_TESTS,
     *   and runTest(i) for i < testNumber has previously been called (once
     *   each.)
     */
    public boolean runTest(int testNumber) throws Exception {
 boolean r = true;
    
 final String afs1NAME= "Last Gasp", afs2NAME= "Wheezers",
     chamber1ADDRESS= "151 Davenport", chamber2ADDRESS= "3030 Yonge",
     breather1NAME= "Adam", breather2NAME= "Eve";
 final double afs1PRICE= 13.00, afs2PRICE= 27.95,
     breather1MONEY= 141.93, breather2MONEY= 683.56;
 final int breather1CAP= 10, breather2CAP= 15;
    
 AirFillShop afs1= null, afs2= null;
 Chamber chamber1= null, chamber2= null;
 Breather breather1= null, breather2= null;
 int litres1, litres2;
 double money1, money2;
 Class breather= Class.forName("Breather");
 Class airFillShop= Class.forName("AirFillShop");
 Class chamber= Class.forName("Chamber");
 Constructor[] airFillShopConstructors= airFillShop.getDeclaredConstructors();
 Constructor[] breatherConstructors= breather.getDeclaredConstructors();
 Constructor[] chamberConstructors= chamber.getDeclaredConstructors();
 Method[] airFillShopMethods= airFillShop.getDeclaredMethods();
 Method[] chamberMethods= chamber.getDeclaredMethods();
 Method[] breatherMethods= breather.getDeclaredMethods();
    
 switch (testNumber) {
      
 case 0:
     // AirFillShop first constructor runs
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     break;
        
 case 1:
     // AirFillShop second constructor runs
     afs1= new AirFillShop("" + afs1PRICE + ", " + afs1NAME);
     break;
        
 case 2:
     // AirFillShop first constructor sets up name correctly
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     r= r &&
  afs1.getName().equals(afs1NAME);
     break;
        
 case 3:
     // AirFillShop second constructor sets up name correctly
     afs1= new AirFillShop("" + afs1PRICE + ", " + afs1NAME);
     r= r &&
  afs1.getName().equals(afs1NAME);
     break;
        
 case 4:
     // AirFillShop first constructor sets up mL/dollar properly
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     r= r &&
  afs1.getMLPerDollar() - 76.92307692307692 < 0.00000000001;
     break;
        
 case 5:
     // AirFillShop second constructor sets up mL/dollar properly
     afs1= new AirFillShop("" + afs1PRICE + ", " + afs1NAME);
     r= r &&
  afs1.getMLPerDollar() - 76.92307692307692 < 0.00000000001;
     break;
        
 case 6:
     // test AirFillShop.sellAir() and AirFillShop.getTotalIncome
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     afs2= new AirFillShop(afs2PRICE, afs2NAME);
     litres1= afs1.sellAir(breather1MONEY);
     litres2= afs2.sellAir(breather2MONEY);
     r= r &&
  litres1 == (int)(breather1MONEY / afs1PRICE) &&
  litres2 == (int) (breather2MONEY / afs2PRICE) &&
  AirFillShop.getTotalIncome() - 
  (breather1MONEY + breather2MONEY) < 0.00000000001;
     break;
        
 case 7:
     // are instance variables really instance?
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     afs2= new AirFillShop(afs2PRICE, afs2NAME);
     r= r &&
  afs1.getMLPerDollar() - 76.92307692307692 < 0.00000000001 &&
  afs2.getMLPerDollar() - 35.77817531305904 < 0.00000000001 &&
  afs1.getName().equals("Last Gasp") &&
  afs2.getName().equals("Wheezers");
     break;
        
 case 8:
     // Chamber first constructor runs
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     chamber1= new Chamber(chamber1ADDRESS, afs1);
     break;
        
 case 9:
     // Chamber second constructor runs
     chamber1= new Chamber(chamber1ADDRESS);
     break;
        
 case 10:
     // Chamber constructor 1 sets up address and air fill shop correctly
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     chamber1= new Chamber(chamber1ADDRESS, afs1);
     r= r &&
  chamber1.getAddress().equals(chamber1ADDRESS) &&
  chamber1.getNearestAirFillShop().equals(afs1); // primitive equals
     break;
        
 case 11:
     // Chamber constructor 2 sets up address correctly
     chamber1= new Chamber(chamber1ADDRESS);
     r= r &&
  chamber1.getAddress().equals(chamber1ADDRESS);
     break;
        
 case 12:
     // Chamber.setNearestAirFillShop takes an AirFillShop
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     chamber1= new Chamber(chamber1ADDRESS);
     chamber1.setNearestAirFillShop(afs1);
     break;
        
 case 13:
     // Chamber.setNearestAirFillShop works, part I
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     chamber1= new Chamber(chamber1ADDRESS);
     chamber1.setNearestAirFillShop(afs1);
     r= r &&
  chamber1.getNearestAirFillShop().equals(afs1); // primitive equals
     break;
        
 case 14:
     // check Chamber.setNearestAirFillShop, part II
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     afs2= new AirFillShop(afs2PRICE, afs2NAME);
     chamber1= new Chamber(chamber1ADDRESS, afs1);
     chamber2= new Chamber(chamber2ADDRESS, afs2);
     chamber1.setNearestAirFillShop(afs2);
     chamber2.setNearestAirFillShop(afs1);
     r= r &&
  chamber1.getNearestAirFillShop().equals(afs2) &&
  chamber2.getNearestAirFillShop().equals(afs1); // primitive equals, for now
     break;
        
 case 15:
     // check Chamber.adjustAirBy() and Chamber.getAvailableAir()
     chamber1= new Chamber(chamber1ADDRESS);
     chamber1.adjustAirBy(53);
     chamber1.adjustAirBy(-46);
     r= r &&
  chamber1.getAvailableAir() == 7;
     break;
        
 case 16:
     // check Chamber.toString()
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     chamber1= new Chamber(chamber1ADDRESS, afs1);
     chamber1.adjustAirBy(66);
     r = r &&
  chamber1.toString().equals(
                             "Chamber: " + chamber1ADDRESS +
                             ", Air (in litres): " + 66 +
                             ", Air fill shop: " +
                             afs1.getName() + ".");
     break;
        
 case 17:
     // are all Chamber instance variables really instance?
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     afs2= new AirFillShop(afs2PRICE, afs2NAME);
     chamber1= new Chamber(chamber1ADDRESS, afs1);
     chamber2= new Chamber(chamber2ADDRESS, afs2);
     chamber1.adjustAirBy(15);
     chamber2.adjustAirBy(20);
     r= r &&
  chamber1.getNearestAirFillShop().equals(afs1) &&
  chamber2.getNearestAirFillShop().equals(afs2) &&
  chamber1.getAvailableAir() == 15 &&
  chamber2.getAvailableAir() == 20;
     break;
        
 case 18:
     // Breather constructor 1 doesn't crash
     breather1= new Breather(breather1NAME, breather1CAP);
     break;
        
 case 19:
     // Breather constructor 2 doesn't crash
     breather1= new Breather(breather1NAME, breather1CAP, breather1MONEY);
     break;
        
 case 20:
     // Breather constructor 3 doesn't crash
     breather1= new Breather(breather1NAME + ", " + breather1CAP +
        ", " + breather1MONEY);
     break;
        
 case 21:
     // Breather construcor 4 doesn't crash
     chamber1= new Chamber(chamber1ADDRESS);
     breather1= new Breather(breather1NAME, breather1CAP, breather1MONEY,
        chamber1);
     break;
        
 case 22:
     // Breather construcor 4 toString() okay
     chamber1= new Chamber(chamber1ADDRESS);
     breather1= new Breather(breather1NAME, breather1CAP, breather1MONEY,
        chamber1);
     r= r &&
  breather1.toString().equals(breather1NAME + ", breathes at " +
         chamber1ADDRESS + ", has $" +
         breather1MONEY + ", can breathe: " +
         breather1.canBreathe() + ".");
     break;
        
 case 23:
     // Breather buys air
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     chamber1= new Chamber(chamber1ADDRESS, afs1);
     money1= AirFillShop.getTotalIncome();
     breather1= new Breather(breather1NAME, breather1CAP, breather1MONEY,
        chamber1);
     breather1.buyAir();
     r = r &&
  breather1.toString().equals(breather1NAME + ", breathes at " +
         chamber1ADDRESS + ", has $" +
         0.0 + ", can breathe: " +
         "true.") &&
  chamber1.getAvailableAir() == (int) (breather1MONEY / afs1PRICE) &&
  AirFillShop.getTotalIncome() == money1 + breather1MONEY;
     break;
        
 case 24:
     // check out Breather.canBreathe()
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     chamber1= new Chamber(chamber1ADDRESS, afs1);
     breather1= new Breather(breather1NAME, breather1CAP, breather1MONEY,
        chamber1);
     r= r &&
  !breather1.canBreathe();
     breather1.buyAir();
     r= r &&
  breather1.canBreathe();
     break;
        
 case 25:
     // check out Breather.canBreathe(), after breathing
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     chamber1= new Chamber(chamber1ADDRESS, afs1);
     breather1= new Breather(breather1NAME, breather1CAP, breather1MONEY,
        chamber1);
     r= r &&
  !breather1.canBreathe();
     breather1.buyAir();
     r= r &&
  breather1.canBreathe();
     breather1.breathe();
     r= r &&
  !breather1.canBreathe();
     break;
        
 case 26:
     // 2 Breathers share a Chamber
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     chamber1= new Chamber(chamber1ADDRESS, afs1);
     breather1= new Breather(breather1NAME, breather1CAP, breather1MONEY,
        chamber1);
     breather2= new Breather(breather2NAME, breather2CAP, breather2MONEY,
        chamber1);
     breather1.buyAir();
     breather2.buyAir();
     r= r &&
  chamber1.getAvailableAir() == (int) (breather1MONEY / afs1PRICE) +
  (int) (breather2MONEY / afs1PRICE);
     break;
        
 case 27:
     // check Breather.earnMoney()
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     chamber1= new Chamber(chamber1ADDRESS, afs1);
     breather1= new Breather(breather1NAME, breather1CAP, breather1MONEY,
        chamber1);
     breather1.earnMoney(1.5);
     r = r &&
  breather1.toString().equals(
         breather1NAME + ", breathes at " +
         chamber1ADDRESS + ", has $" +
         (breather1MONEY + 1.5) + ", can breathe: " +
         "false.");

     break;
        
 case 28:
     // check Breather.move()
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     afs2= new AirFillShop(afs2PRICE, afs2NAME);
     chamber1= new Chamber(chamber1ADDRESS, afs1);
     chamber2= new Chamber(chamber2ADDRESS, afs2);
     breather1= new Breather(breather1NAME, breather1CAP, breather1MONEY,
        chamber1);
     breather1.move(chamber2);
     r= r &&
  breather1.toString().equals(
         breather1NAME + ", breathes at " +
         chamber2ADDRESS + ", has $" +
         breather1MONEY + ", can breathe: " +
         "false.");
     break;
        
 case 29:
     // are instance variables really instance?
     afs1= new AirFillShop(afs1PRICE, afs1NAME);
     afs2= new AirFillShop(afs2PRICE, afs2NAME);
     chamber1= new Chamber(chamber1ADDRESS, afs1);
     chamber2= new Chamber(chamber2ADDRESS, afs2);
     breather1= new Breather(breather1NAME, breather1CAP, breather1MONEY,
        chamber1);
     breather2= new Breather(breather2NAME, breather2CAP, breather2MONEY,
        chamber2);
     r= r &&
  breather1.toString().equals(
         breather1NAME + ", breathes at " +
         chamber1ADDRESS + ", has $" +
         breather1MONEY + ", can breathe: " +
         "false.") &&
  breather2.toString().equals(
         breather2NAME + ", breathes at " +
         chamber2ADDRESS + ", has $" +
         breather2MONEY + ", can breathe: " +
         "false.");
     break;
        
 case 30:
     // check that only AirFillShop constructors of the appropriate
     // signature are created
     for (int i= 0; i != airFillShopConstructors.length; i++) {
  r= r &&
      (airFillShopConstructors[i].toString().equals(
          "public AirFillShop" +
          "(double,java.lang.String)") ||
       airFillShopConstructors[i].toString().equals("public AirFillShop" +
          "(java.lang.String)"));
     }
     break;

 case 31:
     // Check that only Chamber constructors of the appropriate
     // signature are created
     for (int i= 0; i != chamberConstructors.length; i++) {
  r= r &&
      (chamberConstructors[i].toString().equals("public Chamber" +
             "(java.lang.String,AirFillShop)") ||
       chamberConstructors[i].toString().equals("public Chamber" +
             "(java.lang.String)"));
     }
     break;
        
 case 32:
     // check that only constructors with the appropriate signature
     // were created for Breather
     for (int i= 0; i != breatherConstructors.length; i++) {
  r= r &&
      (breatherConstructors[i].toString().equals("public Breather" +
              "(java.lang.String,int)") ||
       breatherConstructors[i].toString().equals("public Breather" +
              "(java.lang.String,int,double)") ||
       breatherConstructors[i].toString().equals("public Breather" +
              "(java.lang.String)") ||
       breatherConstructors[i].toString().equals("public Breather" +
              "(java.lang.String,int,double" +
              ",Chamber)"));
     }
     break;

 case 33:
     // Check AirFillShop method signatures
     String afsMethods= "public static double AirFillShop.getTotalIncome()" +
  "public java.lang.String AirFillShop.toString()" +
  "public java.lang.String AirFillShop.getName()" +
  "public int AirFillShop.sellAir(double)" +
  "public double AirFillShop.getMLPerDollar()";
     for (int i= 0; i != airFillShopMethods.length; i++) {
  r= r &&
      -1 != afsMethods.indexOf(airFillShopMethods[i].toString());
     }
     break;
        
 case 34:
     // Check Chamber method signatures
     String cMethods= "public java.lang.String Chamber.toString()" +
  "public java.lang.String Chamber.getAddress()" +
  "public int Chamber.getAvailableAir()" +
  "public AirFillShop Chamber.getNearestAirFillShop()" +
  "public void Chamber.adjustAirBy(int)" +
  "public void Chamber.setNearestAirFillShop(AirFillShop)";
     for (int i= 0; i != chamberMethods.length; i++) {
  r= r &&
      -1 != cMethods.indexOf(chamberMethods[i].toString());
     }
     break;
        
 case 35:
     // Check Breather method signatures
     String bMethods= "public void Breather.buyAir()" +
  "public void Breather.move(Chamber)" +
  "public void Breather.earnMoney(double)" +
  "public void Breather.breathe()" +
  "public boolean Breather.canBreathe()" +
  "public java.lang.String Breather.toString()";
     for (int i= 0; i != breatherMethods.length; i++) {
  r= r &&
      -1 != bMethods.indexOf(breatherMethods[i].toString());
     }
     break;
        
 case 36:
     // Does AirFillShopTester call sellAir?
     r= r &&
  structureChecker.stringFound("AirFillShopTester", "^.*sellAir\\s*\\(.*$", 36);
     break;
        
 case 37:
     // Does AirFillShopTester call getMLPerDollar
     r= r &&
  structureChecker.stringFound("AirFillShopTester", "^.*getMLPerDollar\\s*\\(.*$",37);
     break;
        
 case 38:
     // Does AirFillShopTester call getName
     r= r &&
  structureChecker.stringFound("AirFillShopTester", "^.*getName\\s*\\(.*$",38);
     break;
        
 case 39:
     // Does AirFillShopTester call getTotalIncome?
     r= r &&
  structureChecker.stringFound("AirFillShopTester", "^.*getTotalIncome\\s*\\(.*$", 39);
     break;
        
 case 40:
     // Does AirFillShopTester call toString?
     r= r &&
  structureChecker.stringFound("AirFillShopTester", "^.*toString\\s*\\(.*$", 40);
     break;
        
 case 41:
     // Does ChamberTester call getAddress?
     r= r &&
  structureChecker.stringFound("ChamberTester", "^.*getAddress\\s*\\(.*$", 41);
     break;
        
 case 42:
     // Does ChamberTester call adjustAirBy?
     r= r &&
  structureChecker.stringFound("ChamberTester", "^.*adjustAirBy\\s*\\(.*$", 42);
     break;
        
 case 43:
     // Does ChamberTester call getAvailableAir?
     r= r &&
  structureChecker.stringFound("ChamberTester", "^.*getAvailableAir\\s*\\(.*$", 43);
     break;
       
 case 44:
     // Does ChamberTester call setNearestAirFillShop
     r= r &&
  structureChecker.stringFound("ChamberTester", "^.*setNearestAirFillShop\\s*\\(.*$", 44);
     break;
        
 case 45:
     // Does ChamberTester call getNearestAirFillShop
     r= r &&
  structureChecker.stringFound("ChamberTester", "^.*getNearestAirFillShop\\s*\\(.*$", 45);
     break;
        
 case 46:
     // Does ChamberTester call toString?
     r= r &&
  structureChecker.stringFound("ChamberTester", "^.*toString\\s*\\(.*$", 46);
     break;
        
 case 47:
     // Does BreatherTester call buyAir
     r= r &&
  structureChecker.stringFound("BreatherTester", "^.*buyAir\\s*\\(.*$", 47);
     break;

 case 48:
     // Does BreatherTester call breathe?
     r= r &&
  structureChecker.
  stringFound("BreatherTester", "^.*breathe\\s*\\(.*$", 48);
     break;
        
 case 49:
     // Does BreatherTester call canBreathe
     r= r &&
  structureChecker.
  stringFound("BreatherTester", "^.*canBreathe\\s*\\(.*$", 49);
     break;

 case 50:
     // Does BreatherTester call earnMoney
     r= r &&
     structureChecker.
  stringFound("BreatherTester", "^.*earnMoney\\s*\\(.*$", 50);
     break;

 case 51:
     // Does BreatherTester call move?
     r= r &&
  structureChecker.
  stringFound("BreatherTester", "^.*move\\s*\\(.*$", 51);
     break;

 case 52:
     // Does BreatherTester call toString?
     r= r &&
  structureChecker.
  stringFound("BreatherTester", "^.*toString\\s*\\(.*$", 52);
     break;
  
 case 53:
     // Are instance variables public in AirFillShop
     r= r &&
  structureChecker.
  badModifierCount("AirFillShop", Modifier.PUBLIC,
     "field", "public field in ", 53) < 1;
     break;
        
 case 54:
     // Are instance variables public in Chamber
     r= r &&
  structureChecker.
  badModifierCount("Chamber", Modifier.PUBLIC,
     "field", "public field in ", 54) < 1;
     break;
        
 case 55:
     // Are instance variables public in Breather
     r= r &&
  structureChecker.
  badModifierCount("Breather", Modifier.PUBLIC,
     "field", "public field in ", 55) < 1;
     break;

 case 56:
     // Proper capitalization in AirFillShop
     r = r &&
  structureChecker.
  badCapitalizationCount("AirFillShop",
           "Bad capitalization: ", 56) < 1;
     break;
        
 case 57:
     // Proper capitalization in Chamber
     r = r &&
  structureChecker.
  badCapitalizationCount("Chamber",
           "Bad capitalization: ", 57) < 1;
     break;
        
 case 58:
     // Proper capitalization in Breather
     r = r &&
  structureChecker.
  badCapitalizationCount("Breather",
           "Bad capitalization: ", 58) < 1;
     break;
        
 case 59:
     // Proper capitalization in AirFillShopTester
     r = r &&
  structureChecker.
  badCapitalizationCount("AirFillShopTester",
           "Bad capitalization: ", 59) < 1;
     break;
        
 case 60:
     // Proper capitalization in ChamberTester
     r = r &&
  structureChecker.
  badCapitalizationCount("ChamberTester",
           "Bad capitalization: ", 60) < 1;
     break;
        
 case 61:
     // Proper capitalization in BreatherTester
     r = r &&
  structureChecker.
  badCapitalizationCount("BreatherTester",
           "Bad capitalization: ", 61) < 1;
     break;

 case 62:
     // No print statements in AirFillShop
     r= r &&
  structureChecker.
  badPrintCount("AirFillShop", 62) < 1;
     break;

 case 63:
     // No print statements in Chamber
     r= r &&
  structureChecker.
  badPrintCount("Chamber", 63) < 1;
     break;

 case 64:
     // No print statements in Breather
     r= r &&
  structureChecker.
  badPrintCount("Breather", 64) < 1;
     break;

 case 65:
     // No loops or ifs in AirFillShop
     r= r &&
  structureChecker.
  badLoopIfCount("AirFillShop", 65) < 1;
     break;

 case 66:
     // No loops or ifs in Chamber
     r= r &&
  structureChecker.
  badLoopIfCount("Chamber", 66) < 1;
     break;

 case 67:
     // No loops or ifs in Breather
     r= r &&
  structureChecker.
  badLoopIfCount("Breather", 67) < 1;
     break;

 case 68:
     // No loops or ifs in AirFillShopTester
     r= r &&
  structureChecker.
  badLoopIfCount("AirFillShopTester", 68) < 1;
     break;

 case 69:
     // No loops or ifs in ChamberTester
     r= r &&
  structureChecker.
  badLoopIfCount("ChamberTester", 69) < 1;
     break;

 case 70:
     // No loops or ifs in BreatherTester
     r= r &&
  structureChecker.
  badLoopIfCount("BreatherTester", 70) < 1;
     break;


 default:
     throw new java.lang.Error();
 }
    
 return r;
    }
}


