You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MemberInitializationsAfterExplicitConstructorCallsCoverage.java 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. // todo: need header
  2. import org.aspectj.testing.Tester;
  3. /**
  4. * "Coverage" tests for
  5. * PR#476:
  6. * Member initializations are run after explicit
  7. * constructor calls ("this()" or "super()") when they should be run beforehand.
  8. * <p>Status:
  9. * 10 additional variants are defined, 5 of which fail, emitting 30 errors.
  10. * <p>background:
  11. * <br>The effective order of operation during initialization should be:
  12. * <ol>
  13. * <ol>superclass static initialization</ol>
  14. * <ol>selfclass static initialization</ol>
  15. * <ol>superclass member initialization</ol>
  16. * <ol>superclass constructor</ol>
  17. * <ol>selfclass member initialization</ol>
  18. * <ol>selfclass constructor</ol>
  19. * </ol>
  20. * Other relevant rules:
  21. * <li>this() or super() if present must be the first statement in a constructor</li>
  22. * <li>Cannot use this (and hence this.member) in either this() or super()
  23. * (checked by javac, not ajc) </li>
  24. * <li>Cannot refer to parent instance members in either this() or super()
  25. * (checked by javac, not ajc) </li>
  26. * <li>an enclosing instance is accessible only in the body of an instance
  27. * method, constructor (after the explicit constructor invocation, if any),
  28. * initializer block, or in the initializer expression of an instance variable.</li>
  29. * <p>fault model:
  30. * the compiler is inserting member initialization after the explicit
  31. * constructor call in the intermediate code. I.e., it produces:
  32. * <pre>ThisCall() {
  33. * this("correctValue");
  34. * {
  35. * this.initString = "INIT";
  36. * this.initNull = null;
  37. * }</pre>
  38. * when it should produce:
  39. * <pre>ThisCall() {
  40. * this("correctValue");</pre>
  41. *
  42. * <p>fix model:
  43. * Since member initialization must occur before this() call,
  44. * and this() must be first in the constructor,
  45. * I see no way to implement before advice on member initializers
  46. * using preprocessing to produce source code except to put them only
  47. * (and always) in the constructors without this() calls.
  48. *
  49. * <p>Variants tested in this coverage extension of the original test case:
  50. * <li>{type}[Object, String, Primitive]: Different member types</li>
  51. * <li>location[top, bottom, mixed]: location of the member initializer in the class declaration -
  52. * before constructor, after constructor</li>
  53. * <li>initializer[simpleExpression, blockExpression, none]:
  54. * type of member initialization
  55. * (<code>Member m = x;<code> or <code>Member m; { m = x; }<code>)
  56. * with location variants. </li>
  57. * <li>initializerLocus[this (default), super, enclosing ]:
  58. * fields being initialized - this instance, superclass, enclosing class
  59. * <li>{enclosingClass}[none, Outer, ]: Different member types</li>
  60. *
  61. * <p>Variants not (yet?) tested:
  62. * <li>static variants</li>
  63. * <li>{super}[{default},Child]: Calling <code>super()</code> rather than <code>this()</code> </li>
  64. *
  65. * <p>Untestable variants:
  66. * <li>Illegal to use this or super member values in explicit constructor call parameter
  67. * evaluation: <code>super("result: " + member)</code>
  68. * or <code>this("result: " + member)</code>.
  69. * or <code>this("result: " + super.member)</code>.
  70. *
  71. * $Id: MemberInitializationsAfterExplicitConstructorCallsCoverage.java,v 1.2 2001/08/03 22:38:49 isberg Exp $
  72. */
  73. public class MemberInitializationsAfterExplicitConstructorCallsCoverage {
  74. public static final String INPUT = "input";
  75. public static final String INIT = "INIT";
  76. public static void main(String[] args) {
  77. test();
  78. }
  79. public static void test() {
  80. boolean doPassingTests = true;
  81. boolean doFailingTests = true;
  82. //--------- proof that test code is correct
  83. { ThisCallTopSimple thisCall = new ThisCallTopSimple(1); thisCall.go(); }
  84. //--------- passing test cases
  85. //--- this duplicates original test case
  86. // ThisCall thisCall;
  87. // no constructor call to this
  88. // thisCall = new ThisCall(INPUT);
  89. // thisCall.go();
  90. //--- new coverage tests - 5 tests, 6 errors each, 30 errors
  91. if (doPassingTests) {
  92. { ThisCallTopSimple thisCall = new ThisCallTopSimple(INPUT); thisCall.go(); }
  93. { ThisCallTopBlock thisCall = new ThisCallTopBlock(INPUT); thisCall.go(); }
  94. { ThisCallBottomSimple thisCall = new ThisCallBottomSimple(INPUT); thisCall.go(); }
  95. { ThisCallBottomBlock thisCall = new ThisCallBottomBlock(INPUT); thisCall.go(); }
  96. { ThisCallMixed thisCall = new ThisCallMixed(INPUT); thisCall.go(); }
  97. // all super cases pass
  98. { ThisCallChild thisCall = new ThisCallChild(); thisCall.go(); }
  99. { ThisCallChild thisCall = new ThisCallChild(2); thisCall.go(); }
  100. { ThisCallChild thisCall = new ThisCallChild(INPUT); thisCall.go(); }
  101. // enclosed inner class initializer can access enclosing members
  102. { ThisCallEnclosing.ThisCallEnclosed thisCall
  103. = (new ThisCallEnclosing("ignored")).new ThisCallEnclosed(); }
  104. }
  105. // { ThisCallChild thisCall = new ThisCallChild(); thisCall.go(); }
  106. //--------- failing test cases
  107. //--- duplicate original test case
  108. // fails - constructor call to this
  109. //thisCall = new ThisCall();
  110. //thisCall.go();
  111. //--- new coverage tests
  112. if (doFailingTests) {
  113. { ThisCallTopSimple thisCall = new ThisCallTopSimple(); thisCall.go(); }
  114. { ThisCallTopBlock thisCall = new ThisCallTopBlock(); thisCall.go(); }
  115. { ThisCallBottomSimple thisCall = new ThisCallBottomSimple(); thisCall.go(); }
  116. { ThisCallBottomBlock thisCall = new ThisCallBottomBlock(); thisCall.go(); }
  117. { ThisCallMixed thisCall = new ThisCallMixed(); thisCall.go(); }
  118. }
  119. //--------- impossible test cases
  120. //---- unable to test superclass initialization before instance
  121. // { ThisCallChild thisCall = new ThisCallChild((long)1l); thisCall.go(); }
  122. }
  123. /** variant: location top, initializer simpleExpression */
  124. static class ThisCallTopSimple {
  125. /** type primitive, location top, initializer simpleExpression */
  126. int initOne = 1;
  127. /** type String, location top, initializer simpleExpression */
  128. String initString = "INIT";
  129. /** type Object, location top, initializer simpleExpression */
  130. Object initNull = null;
  131. /** type String, location top, initializer none */
  132. String initNone;
  133. /** no bug when calling this directly */
  134. ThisCallTopSimple (String input) {
  135. checkMembersHaveInitializedValues("constructor ThisCallTopSimple(\" + input + \")");
  136. setValues(input);
  137. checkMembersHaveSetValues("constructor ThisCallTopSimple.ThisCallTopSimple(\" + input + \")");
  138. }
  139. void setValues(String input) {
  140. this.initString = input;
  141. this.initNull = input;
  142. this.initNone = input;
  143. this.initOne = 2;
  144. }
  145. /** proof that test code is correct */
  146. ThisCallTopSimple (int ignored) {
  147. checkMembersHaveInitializedValues("constructor ThisCallTopSimple.ThisCallTopSimple(int)");
  148. setValues(INPUT);
  149. checkMembersHaveSetValues("constructor ThisCallTopSimple.ThisCallTopSimple(int)");
  150. }
  151. /** bug when calling this which calls ThisCall(String) */
  152. ThisCallTopSimple () {
  153. this(INPUT);
  154. checkMembersHaveSetValues("constructor ThisCallTopSimple.ThisCallTopSimple()");
  155. }
  156. /** redundant check - same check at end of constructors */
  157. void go() {
  158. checkMembersHaveSetValues("method ThisCallTopSimple.go()");
  159. }
  160. /** the same method for all variants */
  161. protected void checkMembersHaveInitializedValues(String label) {
  162. Tester.checkEqual("INIT", initString, label + " initialized ");
  163. Tester.checkEqual((Object) null, initNull, label + " initialized ");
  164. Tester.checkEqual((Object) null, initNone, label + " initialized ");
  165. Tester.checkEqual(1, initOne, label + " initialized ");
  166. }
  167. /** the same method for all variants */
  168. protected void checkMembersHaveSetValues(String label) {
  169. Tester.checkEqual(2, initOne, label + " set ");
  170. Tester.checkEqual("input", initString, label + " set ");
  171. Tester.checkEqual("input", initNone, label + " set ");
  172. // Object uses strict/reference identity - input dependency
  173. Tester.checkEqual(INPUT, initNull, label + " set ");
  174. }
  175. } // ThisCallTopSimple
  176. /** variant: location top, initializer blockExpression */
  177. static class ThisCallTopBlock {
  178. /** top declarations */
  179. /** type primitive, location top, initializer blockExpression */
  180. int initOne;
  181. /** type String, location top, initializer blockExpression */
  182. String initString;
  183. /** type Object, location top, initializer blockExpression */
  184. Object initNull;
  185. /** type String, location top, initializer none */
  186. String initNone;
  187. /** top initializer block */
  188. {
  189. initOne = 1;
  190. initString = "INIT";
  191. initNull = null;
  192. }
  193. /** no bug when calling this directly */
  194. ThisCallTopBlock (String input) {
  195. checkMembersHaveInitializedValues("constructor ThisCallTopBlock(\" + input + \")");
  196. this.initString = input;
  197. this.initNull = input;
  198. this.initNone = input;
  199. this.initOne = 2;
  200. checkMembersHaveSetValues("constructor ThisCallTopSimple.ThisCall(\" + input + \")");
  201. }
  202. /** bug when calling this which calls ThisCallTopBlock(String) */
  203. ThisCallTopBlock () {
  204. this(INPUT);
  205. checkMembersHaveSetValues("constructor ThisCallTopSimple.ThisCallTopBlock()");
  206. }
  207. /** redundant check - same check at end of constructors */
  208. void go() {
  209. checkMembersHaveSetValues("method ThisCallTopBlock.go()");
  210. }
  211. /** the same method for all variants */
  212. protected void checkMembersHaveInitializedValues(String label) {
  213. Tester.checkEqual("INIT", initString, label + " initialized ");
  214. Tester.checkEqual((Object) null, initNull, label + " initialized ");
  215. Tester.checkEqual((Object) null, initNone, label + " initialized ");
  216. Tester.checkEqual(1, initOne, label + " initialized ");
  217. }
  218. /** the same method for all variants */
  219. protected void checkMembersHaveSetValues(String label) {
  220. Tester.checkEqual(2, initOne, label + " set ");
  221. Tester.checkEqual("input", initString, label + " set ");
  222. Tester.checkEqual("input", initNone, label + " set ");
  223. // Object uses strict/reference identity - input dependency
  224. Tester.checkEqual(INPUT, initNull, label + " set ");
  225. }
  226. } // ThisCallTopBlock
  227. /** variant: location bottom, initializer simpleExpression */
  228. static class ThisCallBottomSimple {
  229. /** no bug when calling this directly */
  230. ThisCallBottomSimple (String input) {
  231. checkMembersHaveInitializedValues("constructor ThisCallBottomSimple(\" + input + \")");
  232. this.initString = input;
  233. this.initNull = input;
  234. this.initNone = input;
  235. this.initOne = 2;
  236. checkMembersHaveSetValues("constructor ThisCallBottomSimple.ThisCallBottomSimple(\" + input + \")");
  237. }
  238. /** bug when calling this which calls ThisCallBottomSimple(String) */
  239. ThisCallBottomSimple () {
  240. this(INPUT);
  241. checkMembersHaveSetValues("constructor ThisCallBottomSimple.ThisCallBottomSimple()");
  242. }
  243. /** redundant check - same check at end of constructors */
  244. void go() {
  245. checkMembersHaveSetValues("method ThisCallBottomSimple.go()");
  246. }
  247. /** the same method for all variants */
  248. protected void checkMembersHaveInitializedValues(String label) {
  249. Tester.checkEqual("INIT", initString, label + " initialized ");
  250. Tester.checkEqual((Object) null, initNull, label + " initialized ");
  251. Tester.checkEqual((Object) null, initNone, label + " initialized ");
  252. Tester.checkEqual(1, initOne, label + " initialized ");
  253. }
  254. /** the same method for all variants */
  255. protected void checkMembersHaveSetValues(String label) {
  256. Tester.checkEqual(2, initOne, label + " set ");
  257. Tester.checkEqual("input", initString, label + " set ");
  258. Tester.checkEqual("input", initNone, label + " set ");
  259. // Object uses strict/reference identity - input dependency
  260. Tester.checkEqual(INPUT, initNull, label + " set ");
  261. }
  262. /** type primitive, location bottom, initializer simpleExpression */
  263. int initOne = 1;
  264. /** type String, location bottom, initializer simpleExpression */
  265. String initString = "INIT";
  266. /** type Object, location bottom, initializer simpleExpression */
  267. Object initNull = null;
  268. /** type String, location bottom, initializer none */
  269. String initNone;
  270. } // ThisCallBottomSimple
  271. /** variant: location bottom, initializer blockExpression */
  272. static class ThisCallBottomBlock {
  273. /** no bug when calling this directly */
  274. ThisCallBottomBlock (String input) {
  275. checkMembersHaveInitializedValues("constructor ThisCallBottomBlock(\" + input + \")");
  276. this.initString = input;
  277. this.initNull = input;
  278. this.initNone = input;
  279. this.initOne = 2;
  280. checkMembersHaveSetValues("constructor ThisCallBottomBlock.ThisCallBottomBlock(\" + input + \")");
  281. }
  282. /** bug when calling this which calls ThisCallBottomBlock(String) */
  283. ThisCallBottomBlock () {
  284. this(INPUT);
  285. checkMembersHaveSetValues("constructor ThisCallBottemBlock.ThisCallBottomBlock()");
  286. }
  287. /** redundant check - same check at end of constructors */
  288. void go() {
  289. checkMembersHaveSetValues("method ThisCallBottomBlock.go()");
  290. }
  291. /** the same method for all variants */
  292. protected void checkMembersHaveInitializedValues(String label) {
  293. Tester.checkEqual("INIT", initString, label + " initialized ");
  294. Tester.checkEqual((Object) null, initNull, label + " initialized ");
  295. Tester.checkEqual((Object) null, initNone, label + " initialized ");
  296. Tester.checkEqual(1, initOne, label + " initialized ");
  297. }
  298. /** the same method for all variants */
  299. protected void checkMembersHaveSetValues(String label) {
  300. Tester.checkEqual(2, initOne, label + " set ");
  301. Tester.checkEqual("input", initString, label + " set ");
  302. Tester.checkEqual("input", initNone, label + " set ");
  303. // Object uses strict/reference identity - input dependency
  304. Tester.checkEqual(INPUT, initNull, label + " set ");
  305. }
  306. /** bottom declarations */
  307. /** type primitive, location bottom, initializer blockExpression */
  308. int initOne;
  309. /** type String, location bottom, initializer blockExpression */
  310. String initString;
  311. /** type Object, location bottom, initializer blockExpression */
  312. Object initNull;
  313. /** type String, location bottom, initializer none */
  314. String initNone;
  315. /** bottom initializer block */
  316. {
  317. initOne = 1;
  318. initString = "INIT";
  319. initNull = null;
  320. }
  321. } // ThisCallBottomBlock
  322. /** variant: location mixed, initializer mixed */
  323. static class ThisCallMixed {
  324. /** type primitive, location top, initializer simpleExpression */
  325. int initOne = 1;
  326. /** type String, location top, initializer simpleExpression */
  327. String initString;
  328. /** no bug when calling this directly */
  329. ThisCallMixed (String input) {
  330. checkMembersHaveInitializedValues("constructor ThisCallMixed(\" + input + \")");
  331. this.initString = input;
  332. this.initNull = input;
  333. this.initNone = input;
  334. this.initOne = 2;
  335. checkMembersHaveSetValues("constructor ThisCallMixed.ThisCallMixed(\" + input + \")");
  336. }
  337. /** bug when calling this which calls ThisCallMixed(String) */
  338. ThisCallMixed () {
  339. this(INPUT);
  340. checkMembersHaveSetValues("constructor ThisCallMixed.ThisCallMixed()");
  341. }
  342. /** redundant check - same check at end of constructors */
  343. void go() {
  344. checkMembersHaveSetValues("method ThisCallMixed.go()");
  345. }
  346. /** the same method for all variants */
  347. protected void checkMembersHaveInitializedValues(String label) {
  348. Tester.checkEqual("INIT", initString, label + " initialized ");
  349. Tester.checkEqual((Object) null, initNull, label + " initialized ");
  350. Tester.checkEqual((Object) null, initNone, label + " initialized ");
  351. Tester.checkEqual(1, initOne, label + " initialized ");
  352. }
  353. /** the same method for all variants */
  354. protected void checkMembersHaveSetValues(String label) {
  355. Tester.checkEqual(2, initOne, label + " set ");
  356. Tester.checkEqual("input", initString, label + " set ");
  357. Tester.checkEqual("input", initNone, label + " set ");
  358. // Object uses strict/reference identity - input dependency
  359. Tester.checkEqual(INPUT, initNull, label + " set ");
  360. }
  361. /** bottom declarations */
  362. /** type String, location bottom, initializer none */
  363. String initNone;
  364. /** type Object, location bottom, initializer blockExpression */
  365. Object initNull;
  366. /** bottom (partial) initializer block */
  367. {
  368. initString = "INIT";
  369. initNull = null;
  370. }
  371. } // ThisCallMixed
  372. static class ThisCallChild extends ThisCallParent {
  373. /** type primitive, location top, initializer simpleExpression */
  374. int initOne = 1;
  375. /** type String, location top, initializer simpleExpression */
  376. String initString = "INIT";
  377. /** type Object, location top, initializer simpleExpression */
  378. Object initNull = null;
  379. /** type String, location top, initializer none */
  380. String initNone;
  381. /** no bug when calling this directly */
  382. ThisCallChild (String input) {
  383. checkMembersHaveInitializedValues("constructor ThisCallChild(\" + input + \")");
  384. setValues(input);
  385. checkMembersHaveSetValues("constructor ThisCallChild.ThisCallChild((\" + input + \")");;
  386. Tester.checkEqual(parentObject, INPUT, "ThisCallChild.ThisCallChild(int ignored)");
  387. }
  388. void setValues(String input) {
  389. this.initString = input;
  390. this.initNull = input;
  391. this.initNone = input;
  392. this.initOne = 2;
  393. }
  394. /**
  395. * @param correctResult
  396. * @param actual
  397. * @param expected
  398. * @param failedResult
  399. * @param testerMessage the String to use for Tester on failure -
  400. * Tester unused if null
  401. * @return correctResult if expected.equals(actual), failedResult otherwise
  402. */
  403. static private String checkObject(String correctResult
  404. , Object expected
  405. , Object actual
  406. , String failedResult
  407. , String testerMessage) {
  408. if (null == expected) {
  409. if (null == actual) {
  410. return correctResult;
  411. } // else failures fall through
  412. } else if ((null != actual) && (expected.equals(actual))) {
  413. return correctResult;
  414. }
  415. // failures
  416. if (null != testerMessage) {
  417. Tester.checkEqual(actual, expected, testerMessage);
  418. }
  419. return failedResult;
  420. }
  421. /** proof that test code is correct */
  422. ThisCallChild (int ignored) {
  423. checkMembersHaveInitializedValues("constructor ThisCallChild.ThisCallChild(int)");
  424. setValues(INPUT);
  425. checkMembersHaveSetValues("constructor ThisCallChild.ThisCallChild(int)");
  426. Tester.checkEqual(parentObject, INPUT, "ThisCallChild.ThisCallChild(int ignored)");
  427. }
  428. /** no bug when calling this which calls ThisCall(String) */
  429. ThisCallChild () {
  430. super(INPUT);
  431. checkMembersHaveInitializedValues("constructor ThisCallChild.ThisCallChild()");
  432. setValues(INPUT);
  433. checkMembersHaveSetValues("constructor ThisCallChild.ThisCallChild()");
  434. Tester.checkEqual(parentObject, INPUT, "ThisCallChild.ThisCallChild()");
  435. }
  436. private static final String tccsuperlabel =
  437. "ThisCallChild.ThisCallChild(long)/* parent initialization complete before child */";
  438. /** unable to access superclass member state before explicitly invoking constructor */
  439. ThisCallChild (long ignored) {
  440. // this would do the check, but it is illegal
  441. // this(checkObject(INPUT, INPUT, parentObject, tccsuperLabel + "_FAILED", tccsuperlabel));
  442. // this(checkObject(INPUT, INPUT, this$.getParentObject(), tccsuperlabel + "_FAILED", tccsuperlabel));
  443. checkMembersHaveInitializedValues("constructor ThisCallChild.ThisCallChild()");
  444. setValues(INPUT);
  445. checkMembersHaveSetValues("constructor ThisCallChild.ThisCallChild()");
  446. Tester.checkEqual(parentObject, INPUT, "ThisCallChild.ThisCallChild()");
  447. }
  448. /** redundant check - same check at end of constructors */
  449. void go() {
  450. checkMembersHaveSetValues("method ThisCallChild.go()");
  451. Tester.checkEqual(parentObject, INPUT, "ThisCallChild.go()");
  452. }
  453. /** the same method for all variants */
  454. protected void checkMembersHaveInitializedValues(String label) {
  455. Tester.checkEqual("INIT", initString, label + " initialized ");
  456. Tester.checkEqual((Object) null, initNull, label + " initialized ");
  457. Tester.checkEqual((Object) null, initNone, label + " initialized ");
  458. Tester.checkEqual(1, initOne, label + " initialized ");
  459. }
  460. /** the same method for all variants */
  461. protected void checkMembersHaveSetValues(String label) {
  462. Tester.checkEqual(2, initOne, label + " set ");
  463. Tester.checkEqual("input", initString, label + " set ");
  464. Tester.checkEqual("input", initNone, label + " set ");
  465. // Object uses strict/reference identity - input dependency
  466. Tester.checkEqual(INPUT, initNull, label + " set ");
  467. }
  468. }
  469. static class ThisCallParent {
  470. /** not available to in child explicit constructor parameter expression */
  471. protected Object parentObject = INIT;
  472. /** not available to in child explicit constructor parameter expression */
  473. protected Object getParentObject() { return parentObject; }
  474. /** no bug here */
  475. ThisCallParent() {
  476. Tester.checkEqual(parentObject, INIT, "ThisCallParent.ThisCallParent()");
  477. parentObject = INPUT;
  478. }
  479. /** no bug here */
  480. ThisCallParent(String input) {
  481. Tester.checkEqual(parentObject, INIT, "ThisCallParent.ThisCallParent(\"" + input + "\")");
  482. parentObject = input;
  483. }
  484. }
  485. } // MemberInitializationsAfterExplicitConstructorCallsCoverage
  486. /** variant: location enclosing */
  487. class ThisCallEnclosing {
  488. public static final String INPUT = "input";
  489. public static final String INIT = "INIT";
  490. String initString = INIT;
  491. String constructedString;
  492. public ThisCallEnclosed getEnclosed() {
  493. return new ThisCallEnclosed();
  494. }
  495. /** no bug when calling this directly */
  496. ThisCallEnclosing (String ignored) {
  497. constructedString = INPUT;
  498. initString = INPUT;
  499. }
  500. public class ThisCallEnclosed {
  501. boolean didCheck;
  502. {
  503. // check enclosing instance in initializer
  504. Tester.checkEqual(INPUT, initString, "ThisCallEnclosed.<initializer> initString");
  505. Tester.checkEqual(INPUT, constructedString, "ThisCallEnclosed.<initializer> constructedString");
  506. didCheck = true;
  507. }
  508. public ThisCallEnclosed() {
  509. this("init: " + initString + " constructed: " + constructedString);
  510. Tester.check(didCheck, "initializer ran before ThisCallEnclosed() body");
  511. }
  512. public ThisCallEnclosed(String s) {
  513. Tester.checkEqual(INPUT, initString, "ThisCallEnclosed(String) initString");
  514. Tester.checkEqual(INPUT, constructedString, "ThisCallEnclosed(String) constructedString");
  515. Tester.check(didCheck, "initializer ran before ThisCallEnclosed(String) body");
  516. }
  517. }
  518. } // ThisCallEnclosing