mirror of
https://github.com/eclipse-aspectj/aspectj.git
synced 2024-09-13 15:45:38 +02:00
566 lines
22 KiB
Java
566 lines
22 KiB
Java
// todo: need header
|
|
|
|
import org.aspectj.testing.Tester;
|
|
|
|
/**
|
|
* "Coverage" tests for
|
|
* PR#476:
|
|
* Member initializations are run after explicit
|
|
* constructor calls ("this()" or "super()") when they should be run beforehand.
|
|
* <p>Status:
|
|
* 10 additional variants are defined, 5 of which fail, emitting 30 errors.
|
|
* <p>background:
|
|
* <br>The effective order of operation during initialization should be:
|
|
* <ol>
|
|
* <ol>superclass static initialization</ol>
|
|
* <ol>selfclass static initialization</ol>
|
|
* <ol>superclass member initialization</ol>
|
|
* <ol>superclass constructor</ol>
|
|
* <ol>selfclass member initialization</ol>
|
|
* <ol>selfclass constructor</ol>
|
|
* </ol>
|
|
* Other relevant rules:
|
|
* <li>this() or super() if present must be the first statement in a constructor</li>
|
|
* <li>Cannot use this (and hence this.member) in either this() or super()
|
|
* (checked by javac, not ajc) </li>
|
|
* <li>Cannot refer to parent instance members in either this() or super()
|
|
* (checked by javac, not ajc) </li>
|
|
* <li>an enclosing instance is accessible only in the body of an instance
|
|
* method, constructor (after the explicit constructor invocation, if any),
|
|
* initializer block, or in the initializer expression of an instance variable.</li>
|
|
* <p>fault model:
|
|
* the compiler is inserting member initialization after the explicit
|
|
* constructor call in the intermediate code. I.e., it produces:
|
|
* <pre>ThisCall() {
|
|
* this("correctValue");
|
|
* {
|
|
* this.initString = "INIT";
|
|
* this.initNull = null;
|
|
* }</pre>
|
|
* when it should produce:
|
|
* <pre>ThisCall() {
|
|
* this("correctValue");</pre>
|
|
*
|
|
* <p>fix model:
|
|
* Since member initialization must occur before this() call,
|
|
* and this() must be first in the constructor,
|
|
* I see no way to implement before advice on member initializers
|
|
* using preprocessing to produce source code except to put them only
|
|
* (and always) in the constructors without this() calls.
|
|
*
|
|
* <p>Variants tested in this coverage extension of the original test case:
|
|
* <li>{type}[Object, String, Primitive]: Different member types</li>
|
|
* <li>location[top, bottom, mixed]: location of the member initializer in the class declaration -
|
|
* before constructor, after constructor</li>
|
|
* <li>initializer[simpleExpression, blockExpression, none]:
|
|
* type of member initialization
|
|
* (<code>Member m = x;<code> or <code>Member m; { m = x; }<code>)
|
|
* with location variants. </li>
|
|
* <li>initializerLocus[this (default), super, enclosing ]:
|
|
* fields being initialized - this instance, superclass, enclosing class
|
|
* <li>{enclosingClass}[none, Outer, ]: Different member types</li>
|
|
*
|
|
* <p>Variants not (yet?) tested:
|
|
* <li>static variants</li>
|
|
* <li>{super}[{default},Child]: Calling <code>super()</code> rather than <code>this()</code> </li>
|
|
*
|
|
* <p>Untestable variants:
|
|
* <li>Illegal to use this or super member values in explicit constructor call parameter
|
|
* evaluation: <code>super("result: " + member)</code>
|
|
* or <code>this("result: " + member)</code>.
|
|
* or <code>this("result: " + super.member)</code>.
|
|
*
|
|
* $Id: MemberInitializationsAfterExplicitConstructorCallsCoverage.java,v 1.2 2001/08/03 22:38:49 isberg Exp $
|
|
*/
|
|
public class MemberInitializationsAfterExplicitConstructorCallsCoverage {
|
|
public static final String INPUT = "input";
|
|
public static final String INIT = "INIT";
|
|
public static void main(String[] args) {
|
|
test();
|
|
}
|
|
|
|
public static void test() {
|
|
boolean doPassingTests = true;
|
|
boolean doFailingTests = true;
|
|
//--------- proof that test code is correct
|
|
{ ThisCallTopSimple thisCall = new ThisCallTopSimple(1); thisCall.go(); }
|
|
//--------- passing test cases
|
|
//--- this duplicates original test case
|
|
// ThisCall thisCall;
|
|
// no constructor call to this
|
|
// thisCall = new ThisCall(INPUT);
|
|
// thisCall.go();
|
|
//--- new coverage tests - 5 tests, 6 errors each, 30 errors
|
|
if (doPassingTests) {
|
|
{ ThisCallTopSimple thisCall = new ThisCallTopSimple(INPUT); thisCall.go(); }
|
|
{ ThisCallTopBlock thisCall = new ThisCallTopBlock(INPUT); thisCall.go(); }
|
|
{ ThisCallBottomSimple thisCall = new ThisCallBottomSimple(INPUT); thisCall.go(); }
|
|
{ ThisCallBottomBlock thisCall = new ThisCallBottomBlock(INPUT); thisCall.go(); }
|
|
{ ThisCallMixed thisCall = new ThisCallMixed(INPUT); thisCall.go(); }
|
|
// all super cases pass
|
|
{ ThisCallChild thisCall = new ThisCallChild(); thisCall.go(); }
|
|
{ ThisCallChild thisCall = new ThisCallChild(2); thisCall.go(); }
|
|
{ ThisCallChild thisCall = new ThisCallChild(INPUT); thisCall.go(); }
|
|
// enclosed inner class initializer can access enclosing members
|
|
{ ThisCallEnclosing.ThisCallEnclosed thisCall
|
|
= (new ThisCallEnclosing("ignored")).new ThisCallEnclosed(); }
|
|
}
|
|
// { ThisCallChild thisCall = new ThisCallChild(); thisCall.go(); }
|
|
|
|
//--------- failing test cases
|
|
//--- duplicate original test case
|
|
// fails - constructor call to this
|
|
//thisCall = new ThisCall();
|
|
//thisCall.go();
|
|
//--- new coverage tests
|
|
if (doFailingTests) {
|
|
{ ThisCallTopSimple thisCall = new ThisCallTopSimple(); thisCall.go(); }
|
|
{ ThisCallTopBlock thisCall = new ThisCallTopBlock(); thisCall.go(); }
|
|
{ ThisCallBottomSimple thisCall = new ThisCallBottomSimple(); thisCall.go(); }
|
|
{ ThisCallBottomBlock thisCall = new ThisCallBottomBlock(); thisCall.go(); }
|
|
{ ThisCallMixed thisCall = new ThisCallMixed(); thisCall.go(); }
|
|
}
|
|
|
|
//--------- impossible test cases
|
|
//---- unable to test superclass initialization before instance
|
|
// { ThisCallChild thisCall = new ThisCallChild((long)1l); thisCall.go(); }
|
|
}
|
|
|
|
/** variant: location top, initializer simpleExpression */
|
|
static class ThisCallTopSimple {
|
|
/** type primitive, location top, initializer simpleExpression */
|
|
int initOne = 1;
|
|
/** type String, location top, initializer simpleExpression */
|
|
String initString = "INIT";
|
|
/** type Object, location top, initializer simpleExpression */
|
|
Object initNull = null;
|
|
/** type String, location top, initializer none */
|
|
String initNone;
|
|
|
|
/** no bug when calling this directly */
|
|
ThisCallTopSimple (String input) {
|
|
checkMembersHaveInitializedValues("constructor ThisCallTopSimple(\" + input + \")");
|
|
setValues(input);
|
|
checkMembersHaveSetValues("constructor ThisCallTopSimple.ThisCallTopSimple(\" + input + \")");
|
|
}
|
|
void setValues(String input) {
|
|
this.initString = input;
|
|
this.initNull = input;
|
|
this.initNone = input;
|
|
this.initOne = 2;
|
|
}
|
|
|
|
/** proof that test code is correct */
|
|
ThisCallTopSimple (int ignored) {
|
|
checkMembersHaveInitializedValues("constructor ThisCallTopSimple.ThisCallTopSimple(int)");
|
|
setValues(INPUT);
|
|
checkMembersHaveSetValues("constructor ThisCallTopSimple.ThisCallTopSimple(int)");
|
|
}
|
|
|
|
/** bug when calling this which calls ThisCall(String) */
|
|
ThisCallTopSimple () {
|
|
this(INPUT);
|
|
checkMembersHaveSetValues("constructor ThisCallTopSimple.ThisCallTopSimple()");
|
|
}
|
|
|
|
/** redundant check - same check at end of constructors */
|
|
void go() {
|
|
checkMembersHaveSetValues("method ThisCallTopSimple.go()");
|
|
}
|
|
/** the same method for all variants */
|
|
protected void checkMembersHaveInitializedValues(String label) {
|
|
Tester.checkEqual("INIT", initString, label + " initialized ");
|
|
Tester.checkEqual((Object) null, initNull, label + " initialized ");
|
|
Tester.checkEqual((Object) null, initNone, label + " initialized ");
|
|
Tester.checkEqual(1, initOne, label + " initialized ");
|
|
}
|
|
|
|
/** the same method for all variants */
|
|
protected void checkMembersHaveSetValues(String label) {
|
|
Tester.checkEqual(2, initOne, label + " set ");
|
|
Tester.checkEqual("input", initString, label + " set ");
|
|
Tester.checkEqual("input", initNone, label + " set ");
|
|
// Object uses strict/reference identity - input dependency
|
|
Tester.checkEqual(INPUT, initNull, label + " set ");
|
|
}
|
|
} // ThisCallTopSimple
|
|
|
|
/** variant: location top, initializer blockExpression */
|
|
static class ThisCallTopBlock {
|
|
/** top declarations */
|
|
/** type primitive, location top, initializer blockExpression */
|
|
int initOne;
|
|
/** type String, location top, initializer blockExpression */
|
|
String initString;
|
|
/** type Object, location top, initializer blockExpression */
|
|
Object initNull;
|
|
/** type String, location top, initializer none */
|
|
String initNone;
|
|
|
|
/** top initializer block */
|
|
{
|
|
initOne = 1;
|
|
initString = "INIT";
|
|
initNull = null;
|
|
}
|
|
|
|
/** no bug when calling this directly */
|
|
ThisCallTopBlock (String input) {
|
|
checkMembersHaveInitializedValues("constructor ThisCallTopBlock(\" + input + \")");
|
|
this.initString = input;
|
|
this.initNull = input;
|
|
this.initNone = input;
|
|
this.initOne = 2;
|
|
checkMembersHaveSetValues("constructor ThisCallTopSimple.ThisCall(\" + input + \")");
|
|
}
|
|
|
|
/** bug when calling this which calls ThisCallTopBlock(String) */
|
|
ThisCallTopBlock () {
|
|
this(INPUT);
|
|
checkMembersHaveSetValues("constructor ThisCallTopSimple.ThisCallTopBlock()");
|
|
}
|
|
|
|
/** redundant check - same check at end of constructors */
|
|
void go() {
|
|
checkMembersHaveSetValues("method ThisCallTopBlock.go()");
|
|
}
|
|
|
|
/** the same method for all variants */
|
|
protected void checkMembersHaveInitializedValues(String label) {
|
|
Tester.checkEqual("INIT", initString, label + " initialized ");
|
|
Tester.checkEqual((Object) null, initNull, label + " initialized ");
|
|
Tester.checkEqual((Object) null, initNone, label + " initialized ");
|
|
Tester.checkEqual(1, initOne, label + " initialized ");
|
|
}
|
|
|
|
/** the same method for all variants */
|
|
protected void checkMembersHaveSetValues(String label) {
|
|
Tester.checkEqual(2, initOne, label + " set ");
|
|
Tester.checkEqual("input", initString, label + " set ");
|
|
Tester.checkEqual("input", initNone, label + " set ");
|
|
// Object uses strict/reference identity - input dependency
|
|
Tester.checkEqual(INPUT, initNull, label + " set ");
|
|
}
|
|
} // ThisCallTopBlock
|
|
|
|
/** variant: location bottom, initializer simpleExpression */
|
|
static class ThisCallBottomSimple {
|
|
/** no bug when calling this directly */
|
|
ThisCallBottomSimple (String input) {
|
|
checkMembersHaveInitializedValues("constructor ThisCallBottomSimple(\" + input + \")");
|
|
this.initString = input;
|
|
this.initNull = input;
|
|
this.initNone = input;
|
|
this.initOne = 2;
|
|
checkMembersHaveSetValues("constructor ThisCallBottomSimple.ThisCallBottomSimple(\" + input + \")");
|
|
}
|
|
|
|
/** bug when calling this which calls ThisCallBottomSimple(String) */
|
|
ThisCallBottomSimple () {
|
|
this(INPUT);
|
|
checkMembersHaveSetValues("constructor ThisCallBottomSimple.ThisCallBottomSimple()");
|
|
}
|
|
|
|
/** redundant check - same check at end of constructors */
|
|
void go() {
|
|
checkMembersHaveSetValues("method ThisCallBottomSimple.go()");
|
|
}
|
|
|
|
/** the same method for all variants */
|
|
protected void checkMembersHaveInitializedValues(String label) {
|
|
Tester.checkEqual("INIT", initString, label + " initialized ");
|
|
Tester.checkEqual((Object) null, initNull, label + " initialized ");
|
|
Tester.checkEqual((Object) null, initNone, label + " initialized ");
|
|
Tester.checkEqual(1, initOne, label + " initialized ");
|
|
}
|
|
|
|
/** the same method for all variants */
|
|
protected void checkMembersHaveSetValues(String label) {
|
|
Tester.checkEqual(2, initOne, label + " set ");
|
|
Tester.checkEqual("input", initString, label + " set ");
|
|
Tester.checkEqual("input", initNone, label + " set ");
|
|
// Object uses strict/reference identity - input dependency
|
|
Tester.checkEqual(INPUT, initNull, label + " set ");
|
|
}
|
|
/** type primitive, location bottom, initializer simpleExpression */
|
|
int initOne = 1;
|
|
/** type String, location bottom, initializer simpleExpression */
|
|
String initString = "INIT";
|
|
/** type Object, location bottom, initializer simpleExpression */
|
|
Object initNull = null;
|
|
/** type String, location bottom, initializer none */
|
|
String initNone;
|
|
} // ThisCallBottomSimple
|
|
|
|
/** variant: location bottom, initializer blockExpression */
|
|
static class ThisCallBottomBlock {
|
|
/** no bug when calling this directly */
|
|
ThisCallBottomBlock (String input) {
|
|
checkMembersHaveInitializedValues("constructor ThisCallBottomBlock(\" + input + \")");
|
|
this.initString = input;
|
|
this.initNull = input;
|
|
this.initNone = input;
|
|
this.initOne = 2;
|
|
checkMembersHaveSetValues("constructor ThisCallBottomBlock.ThisCallBottomBlock(\" + input + \")");
|
|
}
|
|
|
|
/** bug when calling this which calls ThisCallBottomBlock(String) */
|
|
ThisCallBottomBlock () {
|
|
this(INPUT);
|
|
checkMembersHaveSetValues("constructor ThisCallBottemBlock.ThisCallBottomBlock()");
|
|
}
|
|
|
|
/** redundant check - same check at end of constructors */
|
|
void go() {
|
|
checkMembersHaveSetValues("method ThisCallBottomBlock.go()");
|
|
}
|
|
|
|
/** the same method for all variants */
|
|
protected void checkMembersHaveInitializedValues(String label) {
|
|
Tester.checkEqual("INIT", initString, label + " initialized ");
|
|
Tester.checkEqual((Object) null, initNull, label + " initialized ");
|
|
Tester.checkEqual((Object) null, initNone, label + " initialized ");
|
|
Tester.checkEqual(1, initOne, label + " initialized ");
|
|
}
|
|
|
|
/** the same method for all variants */
|
|
protected void checkMembersHaveSetValues(String label) {
|
|
Tester.checkEqual(2, initOne, label + " set ");
|
|
Tester.checkEqual("input", initString, label + " set ");
|
|
Tester.checkEqual("input", initNone, label + " set ");
|
|
// Object uses strict/reference identity - input dependency
|
|
Tester.checkEqual(INPUT, initNull, label + " set ");
|
|
}
|
|
/** bottom declarations */
|
|
/** type primitive, location bottom, initializer blockExpression */
|
|
int initOne;
|
|
/** type String, location bottom, initializer blockExpression */
|
|
String initString;
|
|
/** type Object, location bottom, initializer blockExpression */
|
|
Object initNull;
|
|
/** type String, location bottom, initializer none */
|
|
String initNone;
|
|
|
|
/** bottom initializer block */
|
|
{
|
|
initOne = 1;
|
|
initString = "INIT";
|
|
initNull = null;
|
|
}
|
|
} // ThisCallBottomBlock
|
|
|
|
/** variant: location mixed, initializer mixed */
|
|
static class ThisCallMixed {
|
|
/** type primitive, location top, initializer simpleExpression */
|
|
int initOne = 1;
|
|
/** type String, location top, initializer simpleExpression */
|
|
String initString;
|
|
|
|
/** no bug when calling this directly */
|
|
ThisCallMixed (String input) {
|
|
checkMembersHaveInitializedValues("constructor ThisCallMixed(\" + input + \")");
|
|
this.initString = input;
|
|
this.initNull = input;
|
|
this.initNone = input;
|
|
this.initOne = 2;
|
|
checkMembersHaveSetValues("constructor ThisCallMixed.ThisCallMixed(\" + input + \")");
|
|
}
|
|
|
|
/** bug when calling this which calls ThisCallMixed(String) */
|
|
ThisCallMixed () {
|
|
this(INPUT);
|
|
checkMembersHaveSetValues("constructor ThisCallMixed.ThisCallMixed()");
|
|
}
|
|
|
|
/** redundant check - same check at end of constructors */
|
|
void go() {
|
|
checkMembersHaveSetValues("method ThisCallMixed.go()");
|
|
}
|
|
|
|
/** the same method for all variants */
|
|
protected void checkMembersHaveInitializedValues(String label) {
|
|
Tester.checkEqual("INIT", initString, label + " initialized ");
|
|
Tester.checkEqual((Object) null, initNull, label + " initialized ");
|
|
Tester.checkEqual((Object) null, initNone, label + " initialized ");
|
|
Tester.checkEqual(1, initOne, label + " initialized ");
|
|
}
|
|
|
|
/** the same method for all variants */
|
|
protected void checkMembersHaveSetValues(String label) {
|
|
Tester.checkEqual(2, initOne, label + " set ");
|
|
Tester.checkEqual("input", initString, label + " set ");
|
|
Tester.checkEqual("input", initNone, label + " set ");
|
|
// Object uses strict/reference identity - input dependency
|
|
Tester.checkEqual(INPUT, initNull, label + " set ");
|
|
}
|
|
/** bottom declarations */
|
|
/** type String, location bottom, initializer none */
|
|
String initNone;
|
|
/** type Object, location bottom, initializer blockExpression */
|
|
Object initNull;
|
|
|
|
/** bottom (partial) initializer block */
|
|
{
|
|
initString = "INIT";
|
|
initNull = null;
|
|
}
|
|
} // ThisCallMixed
|
|
|
|
static class ThisCallChild extends ThisCallParent {
|
|
/** type primitive, location top, initializer simpleExpression */
|
|
int initOne = 1;
|
|
/** type String, location top, initializer simpleExpression */
|
|
String initString = "INIT";
|
|
/** type Object, location top, initializer simpleExpression */
|
|
Object initNull = null;
|
|
/** type String, location top, initializer none */
|
|
String initNone;
|
|
|
|
/** no bug when calling this directly */
|
|
ThisCallChild (String input) {
|
|
checkMembersHaveInitializedValues("constructor ThisCallChild(\" + input + \")");
|
|
setValues(input);
|
|
checkMembersHaveSetValues("constructor ThisCallChild.ThisCallChild((\" + input + \")");;
|
|
Tester.checkEqual(parentObject, INPUT, "ThisCallChild.ThisCallChild(int ignored)");
|
|
}
|
|
void setValues(String input) {
|
|
this.initString = input;
|
|
this.initNull = input;
|
|
this.initNone = input;
|
|
this.initOne = 2;
|
|
}
|
|
|
|
/**
|
|
* @param correctResult
|
|
* @param actual
|
|
* @param expected
|
|
* @param failedResult
|
|
* @param testerMessage the String to use for Tester on failure -
|
|
* Tester unused if null
|
|
* @return correctResult if expected.equals(actual), failedResult otherwise
|
|
*/
|
|
static private String checkObject(String correctResult
|
|
, Object expected
|
|
, Object actual
|
|
, String failedResult
|
|
, String testerMessage) {
|
|
if (null == expected) {
|
|
if (null == actual) {
|
|
return correctResult;
|
|
} // else failures fall through
|
|
} else if ((null != actual) && (expected.equals(actual))) {
|
|
return correctResult;
|
|
}
|
|
// failures
|
|
if (null != testerMessage) {
|
|
Tester.checkEqual(actual, expected, testerMessage);
|
|
}
|
|
return failedResult;
|
|
}
|
|
|
|
/** proof that test code is correct */
|
|
ThisCallChild (int ignored) {
|
|
checkMembersHaveInitializedValues("constructor ThisCallChild.ThisCallChild(int)");
|
|
setValues(INPUT);
|
|
checkMembersHaveSetValues("constructor ThisCallChild.ThisCallChild(int)");
|
|
Tester.checkEqual(parentObject, INPUT, "ThisCallChild.ThisCallChild(int ignored)");
|
|
}
|
|
|
|
/** no bug when calling this which calls ThisCall(String) */
|
|
ThisCallChild () {
|
|
super(INPUT);
|
|
checkMembersHaveInitializedValues("constructor ThisCallChild.ThisCallChild()");
|
|
setValues(INPUT);
|
|
checkMembersHaveSetValues("constructor ThisCallChild.ThisCallChild()");
|
|
Tester.checkEqual(parentObject, INPUT, "ThisCallChild.ThisCallChild()");
|
|
}
|
|
|
|
private static final String tccsuperlabel =
|
|
"ThisCallChild.ThisCallChild(long)/* parent initialization complete before child */";
|
|
/** unable to access superclass member state before explicitly invoking constructor */
|
|
ThisCallChild (long ignored) {
|
|
// this would do the check, but it is illegal
|
|
// this(checkObject(INPUT, INPUT, parentObject, tccsuperLabel + "_FAILED", tccsuperlabel));
|
|
// this(checkObject(INPUT, INPUT, this$.getParentObject(), tccsuperlabel + "_FAILED", tccsuperlabel));
|
|
checkMembersHaveInitializedValues("constructor ThisCallChild.ThisCallChild()");
|
|
setValues(INPUT);
|
|
checkMembersHaveSetValues("constructor ThisCallChild.ThisCallChild()");
|
|
Tester.checkEqual(parentObject, INPUT, "ThisCallChild.ThisCallChild()");
|
|
}
|
|
|
|
/** redundant check - same check at end of constructors */
|
|
void go() {
|
|
checkMembersHaveSetValues("method ThisCallChild.go()");
|
|
Tester.checkEqual(parentObject, INPUT, "ThisCallChild.go()");
|
|
}
|
|
|
|
/** the same method for all variants */
|
|
protected void checkMembersHaveInitializedValues(String label) {
|
|
Tester.checkEqual("INIT", initString, label + " initialized ");
|
|
Tester.checkEqual((Object) null, initNull, label + " initialized ");
|
|
Tester.checkEqual((Object) null, initNone, label + " initialized ");
|
|
Tester.checkEqual(1, initOne, label + " initialized ");
|
|
}
|
|
|
|
/** the same method for all variants */
|
|
protected void checkMembersHaveSetValues(String label) {
|
|
Tester.checkEqual(2, initOne, label + " set ");
|
|
Tester.checkEqual("input", initString, label + " set ");
|
|
Tester.checkEqual("input", initNone, label + " set ");
|
|
// Object uses strict/reference identity - input dependency
|
|
Tester.checkEqual(INPUT, initNull, label + " set ");
|
|
}
|
|
}
|
|
static class ThisCallParent {
|
|
/** not available to in child explicit constructor parameter expression */
|
|
protected Object parentObject = INIT;
|
|
/** not available to in child explicit constructor parameter expression */
|
|
protected Object getParentObject() { return parentObject; }
|
|
/** no bug here */
|
|
ThisCallParent() {
|
|
Tester.checkEqual(parentObject, INIT, "ThisCallParent.ThisCallParent()");
|
|
parentObject = INPUT;
|
|
}
|
|
/** no bug here */
|
|
ThisCallParent(String input) {
|
|
Tester.checkEqual(parentObject, INIT, "ThisCallParent.ThisCallParent(\"" + input + "\")");
|
|
parentObject = input;
|
|
}
|
|
}
|
|
} // MemberInitializationsAfterExplicitConstructorCallsCoverage
|
|
/** variant: location enclosing */
|
|
class ThisCallEnclosing {
|
|
public static final String INPUT = "input";
|
|
public static final String INIT = "INIT";
|
|
String initString = INIT;
|
|
String constructedString;
|
|
public ThisCallEnclosed getEnclosed() {
|
|
return new ThisCallEnclosed();
|
|
}
|
|
/** no bug when calling this directly */
|
|
ThisCallEnclosing (String ignored) {
|
|
constructedString = INPUT;
|
|
initString = INPUT;
|
|
}
|
|
|
|
public class ThisCallEnclosed {
|
|
boolean didCheck;
|
|
{
|
|
// check enclosing instance in initializer
|
|
Tester.checkEqual(INPUT, initString, "ThisCallEnclosed.<initializer> initString");
|
|
Tester.checkEqual(INPUT, constructedString, "ThisCallEnclosed.<initializer> constructedString");
|
|
didCheck = true;
|
|
}
|
|
public ThisCallEnclosed() {
|
|
this("init: " + initString + " constructed: " + constructedString);
|
|
Tester.check(didCheck, "initializer ran before ThisCallEnclosed() body");
|
|
|
|
}
|
|
public ThisCallEnclosed(String s) {
|
|
Tester.checkEqual(INPUT, initString, "ThisCallEnclosed(String) initString");
|
|
Tester.checkEqual(INPUT, constructedString, "ThisCallEnclosed(String) constructedString");
|
|
Tester.check(didCheck, "initializer ran before ThisCallEnclosed(String) body");
|
|
}
|
|
}
|
|
} // ThisCallEnclosing
|