package testcase;

public class Main{
  C c;

  public  void DirectPartsTests(){
    System.out.println("avoids logging print statements in the running application");
    B b = new B(new E());
    C c = new C();

    // immediate part tests
    c.accessDataMember(); // pass Weak Class - pass Strong Class
    b.accessInheritedDataMember(); // pass Weak Class - fail Strong Class
    c.accessDataMembersMember(); // fail Weak Class - fail Strong Class
    b.accessInheritedDataMembersMember(); // fail Weak Class - fail Strong Class
  }

  public void LocallyConstructedTests(){
    // pass
    A a = new A();
    a.foo();

    // fail always
    D d = a.newD();
    d.foo();

    // fail - also pass class memberVar only test
    C c = newC();
    c.foo();

    // fail
    B b = newB();
    b.foo();
  }

  public void ReturnTypeTests(){
    // fail Object - fail Class
    D d = (new A()).newD();
    d.foo();

    // pass
    d = newD();
    d.foo();

    // fail Object - Pass Class!?
    d = (new A()).newD();
    d.foo();
  }

  public void ArgumentTests(A a){
    // pass
    a.foo();

    // fail arguments only test
    // pass if locally constructed is attatched
    B b = new B();
    b.foo();
  }

  public static D newD(){return new D();}
  public static C newC(){return new C();}
  public static B newB(){return new B();}
}

public class A {
  D d;

  public A(){this.d = new D();}
  public D newD(){return new D();}
  public B newB(){return new B();}

  public void foo(){}
}

public class B extends A{
  E e;

  public B(){this.e = new E();}
  public B(E e){this.e = e;}
  public void accessInheritedDataMember(){
    e.d.foo();
  }
  public void accessInheritedDataMembersMember(){
    e.d.f.foo();
  }

  public void foo(){}
}

public class C extends A{
  F f;

  public C(){this.f = new F();}
  public void accessDataMember(){
    f.foo();
  }
  public void accessDataMembersMember(){
    f.g.foo();
  }

  public void foo(){}
}

public class D{
  F f;

  public D(){this.f = new F();}

  public void foo(){}
}

public class E{
  D d;

  public E(){this.d = new D();}

  public void foo(){}
}

public class F{
  G g;

  public F(){this.g = new G();}

  public void foo(){}
}

public class G{

  public void foo(){}
}