1 /*
   2  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 6911256 6964740
  27  * @summary Tests of generated ARM code.
  28  */
  29 
  30 import java.util.List;
  31 import java.util.ArrayList;
  32 
  33 public class ArmTests {
  34     public static void main(String[] args) {
  35         testCreateFailure1();
  36         testCreateFailure2();
  37         testCreateFailure2Nested();
  38         testCreateFailure3();
  39         testCreateFailure3Nested();
  40         testCreateFailure4();
  41         testCreateFailure4Nested();
  42         testCreateFailure5();
  43         testCreateFailure5Nested();
  44 
  45         testCreateSuccess1();
  46         testCreateSuccess2();
  47         testCreateSuccess2Nested();
  48         testCreateSuccess3();
  49         testCreateSuccess3Nested();
  50         testCreateSuccess4();
  51         testCreateSuccess4Nested();
  52         testCreateSuccess5();
  53         testCreateSuccess5Nested();
  54     }
  55 
  56     /*
  57      * The following tests simulate a creation failure of every possible
  58      * resource in an ARM block, and check to make sure that the failure
  59      * prevents creation of subsequent resources, and that all created
  60      * resources are properly closed, even if one or more of the close
  61      * attempts fails.
  62      */
  63 
  64     public static void testCreateFailure1() {
  65         int creationFailuresDetected = 0;
  66         List<Integer> closedList = new ArrayList<Integer>(0);
  67         try (Resource r0 = createResource(0, 0, 0, closedList)) {
  68             throw new AssertionError("Resource creation succeeded");
  69         } catch (Resource.CreateFailException e) {
  70             creationFailuresDetected++;
  71             if (e.resourceId() != 0) {
  72                 throw new AssertionError("Wrong resource creation "
  73                                          + e.resourceId() + " failed");
  74             }
  75         } catch (Resource.CloseFailException e) {
  76             throw new AssertionError("Unexpected CloseFailException: " + e.resourceId());
  77         }
  78         checkForSingleCreationFailure(creationFailuresDetected);
  79         checkClosedList(closedList, 0);
  80     }
  81 
  82     public static void testCreateFailure2() {
  83         for (int createFailureId = 0; createFailureId < 2; createFailureId++) {
  84             for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) {
  85                 int creationFailuresDetected = 0;
  86                 List<Integer> closedList = new ArrayList<Integer>();
  87                 try (Resource r0 = createResource(0, createFailureId, bitMap, closedList);
  88                      Resource r1 = createResource(1, createFailureId, bitMap, closedList)) {
  89                     throw new AssertionError("Entire resource creation succeeded");
  90                 } catch (Resource.CreateFailException e) {
  91                     creationFailuresDetected++;
  92                     checkCreateFailureId(e.resourceId(), createFailureId);
  93                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
  94                 } catch (Resource.CloseFailException e) {
  95                     throw new AssertionError("Secondary exception suppression failed");
  96                 }
  97                 checkForSingleCreationFailure(creationFailuresDetected);
  98                 checkClosedList(closedList, createFailureId);
  99             }
 100         }
 101     }
 102 
 103     public static void testCreateFailure2Nested() {
 104         for (int createFailureId = 0; createFailureId < 2; createFailureId++) {
 105             for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) {
 106                 int creationFailuresDetected = 0;
 107                 List<Integer> closedList = new ArrayList<Integer>();
 108                 try (Resource r0 = createResource(0, createFailureId, bitMap, closedList)) {
 109                     try(Resource r1 = createResource(1, createFailureId, bitMap, closedList)) {
 110                         throw new AssertionError("Entire resource creation succeeded");
 111                     }
 112                 } catch (Resource.CreateFailException e) {
 113                     creationFailuresDetected++;
 114                     checkCreateFailureId(e.resourceId(), createFailureId);
 115                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 116                 } catch (Resource.CloseFailException e) {
 117                     throw new AssertionError("Secondary exception suppression failed");
 118                 }
 119                 checkForSingleCreationFailure(creationFailuresDetected);
 120                 checkClosedList(closedList, createFailureId);
 121             }
 122         }
 123     }
 124 
 125     public static void testCreateFailure3() {
 126         for (int createFailureId = 0; createFailureId < 3; createFailureId++) {
 127             for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) {
 128                 int creationFailuresDetected = 0;
 129                 List<Integer> closedList = new ArrayList<Integer>();
 130                 try (Resource r0 = createResource(0, createFailureId, bitMap, closedList);
 131                      Resource r1 = createResource(1, createFailureId, bitMap, closedList);
 132                      Resource r2 = createResource(2, createFailureId, bitMap, closedList)) {
 133                     throw new AssertionError("Entire resource creation succeeded");
 134                 } catch (Resource.CreateFailException e) {
 135                     creationFailuresDetected++;
 136                     checkCreateFailureId(e.resourceId(), createFailureId);
 137                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 138                 } catch (Resource.CloseFailException e) {
 139                     throw new AssertionError("Secondary exception suppression failed:" + e);
 140                 }
 141                 checkForSingleCreationFailure(creationFailuresDetected);
 142                 checkClosedList(closedList, createFailureId);
 143             }
 144         }
 145     }
 146 
 147     public static void testCreateFailure3Nested() {
 148         for (int createFailureId = 0; createFailureId < 3; createFailureId++) {
 149             for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) {
 150                 int creationFailuresDetected = 0;
 151                 List<Integer> closedList = new ArrayList<Integer>();
 152                 try (Resource r0 = createResource(0, createFailureId, bitMap, closedList)) {
 153                     try (Resource r1 = createResource(1, createFailureId, bitMap, closedList)) {
 154                         try (Resource r2 = createResource(2, createFailureId, bitMap, closedList)) {
 155                             throw new AssertionError("Entire resource creation succeeded");
 156                         }
 157                     }
 158                 } catch (Resource.CreateFailException e) {
 159                     creationFailuresDetected++;
 160                     checkCreateFailureId(e.resourceId(), createFailureId);
 161                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 162                 } catch (Resource.CloseFailException e) {
 163                     throw new AssertionError("Secondary exception suppression failed:" + e);
 164                 }
 165                 checkForSingleCreationFailure(creationFailuresDetected);
 166                 checkClosedList(closedList, createFailureId);
 167             }
 168         }
 169     }
 170 
 171     public static void testCreateFailure4() {
 172         for (int createFailureId = 0; createFailureId < 4; createFailureId++) {
 173             for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) {
 174                 int creationFailuresDetected = 0;
 175                 List<Integer> closedList = new ArrayList<Integer>();
 176                 try (Resource r0 = createResource(0, createFailureId, bitMap, closedList);
 177                      Resource r1 = createResource(1, createFailureId, bitMap, closedList);
 178                      Resource r2 = createResource(2, createFailureId, bitMap, closedList);
 179                      Resource r3 = createResource(3, createFailureId, bitMap, closedList)) {
 180                     throw new AssertionError("Entire resource creation succeeded");
 181                 } catch (Resource.CreateFailException e) {
 182                     creationFailuresDetected++;
 183                     checkCreateFailureId(e.resourceId(), createFailureId);
 184                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 185                 } catch (Resource.CloseFailException e) {
 186                     throw new AssertionError("Secondary exception suppression failed:" + e);
 187                 }
 188                 checkForSingleCreationFailure(creationFailuresDetected);
 189                 checkClosedList(closedList, createFailureId);
 190             }
 191         }
 192     }
 193 
 194     public static void testCreateFailure4Nested() {
 195         for (int createFailureId = 0; createFailureId < 4; createFailureId++) {
 196             for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) {
 197                 int creationFailuresDetected = 0;
 198                 List<Integer> closedList = new ArrayList<Integer>();
 199                 try (Resource r0 = createResource(0, createFailureId, bitMap, closedList)) {
 200                     try (Resource r1 = createResource(1, createFailureId, bitMap, closedList)) {
 201                         try (Resource r2 = createResource(2, createFailureId, bitMap, closedList)) {
 202                             try (Resource r3 = createResource(3, createFailureId, bitMap, closedList)) {
 203                                 throw new AssertionError("Entire resource creation succeeded");
 204                             }
 205                         }
 206                     }
 207                 } catch (Resource.CreateFailException e) {
 208                     creationFailuresDetected++;
 209                     checkCreateFailureId(e.resourceId(), createFailureId);
 210                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 211                 } catch (Resource.CloseFailException e) {
 212                     throw new AssertionError("Secondary exception suppression failed:" + e);
 213                 }
 214                 checkForSingleCreationFailure(creationFailuresDetected);
 215                 checkClosedList(closedList, createFailureId);
 216             }
 217         }
 218     }
 219 
 220     public static void testCreateFailure5() {
 221         for (int createFailureId = 0; createFailureId < 5; createFailureId++) {
 222             for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) {
 223                 int creationFailuresDetected = 0;
 224                 List<Integer> closedList = new ArrayList<Integer>();
 225                 try (Resource r0 = createResource(0, createFailureId, bitMap, closedList);
 226                      Resource r1 = createResource(1, createFailureId, bitMap, closedList);
 227                      Resource r2 = createResource(2, createFailureId, bitMap, closedList);
 228                      Resource r3 = createResource(3, createFailureId, bitMap, closedList);
 229                      Resource r4 = createResource(4, createFailureId, bitMap, closedList)) {
 230                     throw new AssertionError("Entire resource creation succeeded");
 231                 } catch (Resource.CreateFailException e) {
 232                     creationFailuresDetected++;
 233                     checkCreateFailureId(e.resourceId(), createFailureId);
 234                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 235                 } catch (Resource.CloseFailException e) {
 236                     throw new AssertionError("Secondary exception suppression failed:" + e);
 237                 }
 238                 checkForSingleCreationFailure(creationFailuresDetected);
 239                 checkClosedList(closedList, createFailureId);
 240             }
 241         }
 242     }
 243 
 244     public static void testCreateFailure5Nested() {
 245         for (int createFailureId = 0; createFailureId < 5; createFailureId++) {
 246             for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) {
 247                 int creationFailuresDetected = 0;
 248                 List<Integer> closedList = new ArrayList<Integer>();
 249                 try (Resource r0 = createResource(0, createFailureId, bitMap, closedList)) {
 250                     try (Resource r1 = createResource(1, createFailureId, bitMap, closedList)) {
 251                         try (Resource r2 = createResource(2, createFailureId, bitMap, closedList)) {
 252                             try (Resource r3 = createResource(3, createFailureId, bitMap, closedList)) {
 253                                 try (Resource r4 = createResource(4, createFailureId, bitMap, closedList)) {
 254                                     throw new AssertionError("Entire resource creation succeeded");
 255                                 }
 256                             }
 257                         }
 258                     }
 259                 } catch (Resource.CreateFailException e) {
 260                     creationFailuresDetected++;
 261                     checkCreateFailureId(e.resourceId(), createFailureId);
 262                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 263                 } catch (Resource.CloseFailException e) {
 264                     throw new AssertionError("Secondary exception suppression failed:" + e);
 265                 }
 266                 checkForSingleCreationFailure(creationFailuresDetected);
 267                 checkClosedList(closedList, createFailureId);
 268             }
 269         }
 270     }
 271 
 272     /**
 273      * Create a resource with the specified ID. The ID must be less than createFailureId.
 274      * A subsequent attempt to close the resource will fail iff the corresponding bit
 275      * is set in closeFailureBitMap.  When an attempt is made to close this resource,
 276      * its ID will be added to closedList, regardless of whether the attempt succeeds.
 277      *
 278      * @param id the ID of this resource
 279      * @param createFailureId the ID of the resource whose creation will fail
 280      * @param closeFailureBitMap a bit vector describing which resources should throw an 
 281      *        exception when close is attempted
 282      * @param closedList a list on which to record resource close attempts
 283      * @throws AssertionError if no attempt should be made to create this resource
 284      */
 285     private static Resource createResource(int id,
 286                                            int createFailureId,
 287                                            int closeFailureBitMap,
 288                                            List<Integer> closedList) throws Resource.CreateFailException {
 289         if (id > createFailureId)
 290             throw new AssertionError("Resource " + id + " shouldn't be created");
 291         boolean createSucceeds = id != createFailureId;
 292         boolean closeSucceeds = (closeFailureBitMap & (1 << id)) == 0;
 293         return new Resource(id, createSucceeds, closeSucceeds, closedList);
 294     }
 295 
 296 
 297     /**
 298      * Check that an observed creation failure has the expected resource ID.
 299      *
 300      * @param foundId the ID of the resource whose creation failed
 301      * @param expectedId the ID of the resource whose creation should have failed
 302      */
 303     private static void checkCreateFailureId(int foundId, int expectedId) {
 304         if (foundId != expectedId)
 305             throw new AssertionError("Wrong resource creation failed. Found ID "
 306                                      + foundId + " expected " + expectedId);
 307     }
 308 
 309     /**
 310      * Check for proper suppressed exceptions in proper order.
 311      *
 312      * @param suppressedExceptions the suppressed exceptions array returned by
 313      *        getSuppressedExceptions()
 314      * @bitmap a bitmap indicating which suppressed exceptions are expected.
 315      *         Bit i is set iff id should throw a CloseFailException.
 316      */
 317     private static void checkSuppressedExceptions(Throwable[] suppressedExceptions, int bitMap) {
 318         if (suppressedExceptions.length != Integer.bitCount(bitMap))
 319             throw new AssertionError("Expected " + Integer.bitCount(bitMap)
 320                                      + " suppressed exceptions, got " +  suppressedExceptions.length);
 321 
 322         int prevCloseFailExceptionId = Integer.MAX_VALUE;
 323         for (Throwable t : suppressedExceptions) {
 324             int id = ((Resource.CloseFailException) t).resourceId();
 325             if ((1 << id  & bitMap) == 0)
 326                 throw new AssertionError("Unexpected suppressed CloseFailException: " + id);
 327             if (id > prevCloseFailExceptionId)
 328                 throw new AssertionError("Suppressed CloseFailException" + id
 329                                          + " followed " + prevCloseFailExceptionId);
 330         }
 331     }
 332 
 333     /**
 334      * Check that exactly one resource creation failed.
 335      * 
 336      * @param numCreationFailuresDetected the number of creation failures detected
 337      */
 338     private static void checkForSingleCreationFailure(int numCreationFailuresDetected) {
 339         if (numCreationFailuresDetected != 1)
 340             throw new AssertionError("Wrong number of creation failures: "
 341                                      + numCreationFailuresDetected);
 342     }
 343 
 344     /**
 345      * Check that a close was attempted on every resourced that was successfully opened,
 346      * and that the close attempts occurred in the proper order.
 347      * 
 348      * @param closedList the resource IDs of the close attempts, in the order they occurred
 349      * @param the ID of the resource whose creation failed.  Close attempts should occur
 350      *        for all previous resources, in reverse order.
 351      *        
 352      */
 353     private static void checkClosedList(List<Integer> closedList, int createFailureId) {
 354         List<Integer> expectedList = new ArrayList<Integer>(createFailureId);
 355         for (int i = createFailureId - 1; i >= 0; i--)
 356             expectedList.add(i);
 357         if (!closedList.equals(expectedList))
 358             throw new AssertionError("Closing sequence " + closedList + " != " + expectedList);
 359     }
 360 
 361     /*
 362      * The following tests simulate the creation of several resources, followed
 363      * by success or failure of forward processing.  They test that all resources
 364      * are properly closed, even if one or more of the close attempts fails.
 365      */
 366 
 367     public static void testCreateSuccess1() {
 368         for (int bitMap = 0, n = 1 << 1; bitMap < n; bitMap++) {
 369             for (int failure = 0; failure < 2; failure++) {
 370                 List<Integer> closedList = new ArrayList<Integer>();
 371                 try (Resource r0 = createResource(0, bitMap, closedList)) {
 372                     if (failure != 0)
 373                         throw new MyKindOfException();
 374                 } catch (Resource.CreateFailException e) {
 375                     throw new AssertionError(
 376                                              "Resource creation failed: " + e.resourceId());
 377                 } catch (MyKindOfException e) {
 378                     if (failure == 0)
 379                         throw new AssertionError("Unexpected MyKindOfException");
 380                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 381                 } catch (Resource.CloseFailException e) {
 382                     if (failure == 1)
 383                         throw new AssertionError("Secondary exception suppression failed");
 384                     int id = e.resourceId();
 385                     if (bitMap == 0)
 386                         throw new AssertionError("Unexpected CloseFailException: " + id);
 387                     int highestCloseFailBit = Integer.highestOneBit(bitMap);
 388                     if (1 << id != highestCloseFailBit) {
 389                         throw new AssertionError("CloseFailException: got id " + id
 390                                                  + ", expected lg(" + highestCloseFailBit +")");
 391                     }
 392                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit);
 393                 }
 394                 checkClosedList(closedList, 1);
 395             }
 396         }
 397     }
 398 
 399     public static void testCreateSuccess2() {
 400         for (int bitMap = 0, n = 1 << 2; bitMap < n; bitMap++) {
 401             for (int failure = 0; failure < 2; failure++) {
 402                 List<Integer> closedList = new ArrayList<Integer>();
 403                 try (Resource r0 = createResource(0, bitMap, closedList);
 404                      Resource r1 = createResource(1, bitMap, closedList)) {
 405                     if (failure != 0)
 406                         throw new MyKindOfException();
 407                 } catch (Resource.CreateFailException e) {
 408                     throw new AssertionError(
 409                                              "Resource creation failed: " + e.resourceId());
 410                 } catch (MyKindOfException e) {
 411                     if (failure == 0)
 412                         throw new AssertionError("Unexpected MyKindOfException");
 413                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 414                 } catch (Resource.CloseFailException e) {
 415                     if (failure == 1)
 416                         throw new AssertionError("Secondary exception suppression failed");
 417                     int id = e.resourceId();
 418                     if (bitMap == 0)
 419                         throw new AssertionError("Unexpected CloseFailException: " + id);
 420                     int highestCloseFailBit = Integer.highestOneBit(bitMap);
 421                     if (1 << id != highestCloseFailBit) {
 422                         throw new AssertionError("CloseFailException: got id " + id
 423                                                  + ", expected lg(" + highestCloseFailBit +")");
 424                     }
 425                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit);
 426                 }
 427                 checkClosedList(closedList, 2);
 428             }
 429         }
 430     }
 431 
 432     public static void testCreateSuccess2Nested() {
 433         for (int bitMap = 0, n = 1 << 2; bitMap < n; bitMap++) {
 434             for (int failure = 0; failure < 2; failure++) {
 435                 List<Integer> closedList = new ArrayList<Integer>();
 436                 try (Resource r0 = createResource(0, bitMap, closedList)) {
 437                     try (Resource r1 = createResource(1, bitMap, closedList)) {
 438                         if (failure != 0)
 439                             throw new MyKindOfException();
 440                     }
 441                 } catch (Resource.CreateFailException e) {
 442                     throw new AssertionError(
 443                                              "Resource creation failed: " + e.resourceId());
 444                 } catch (MyKindOfException e) {
 445                     if (failure == 0)
 446                         throw new AssertionError("Unexpected MyKindOfException");
 447                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 448                 } catch (Resource.CloseFailException e) {
 449                     if (failure == 1)
 450                         throw new AssertionError("Secondary exception suppression failed");
 451                     int id = e.resourceId();
 452                     if (bitMap == 0)
 453                         throw new AssertionError("Unexpected CloseFailException: " + id);
 454                     int highestCloseFailBit = Integer.highestOneBit(bitMap);
 455                     if (1 << id != highestCloseFailBit) {
 456                         throw new AssertionError("CloseFailException: got id " + id
 457                                                  + ", expected lg(" + highestCloseFailBit +")");
 458                     }
 459                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit);
 460                 }
 461                 checkClosedList(closedList, 2);
 462             }
 463         }
 464     }
 465 
 466     public static void testCreateSuccess3() {
 467         for (int bitMap = 0, n = 1 << 3; bitMap < n; bitMap++) {
 468             for (int failure = 0; failure < 2; failure++) {
 469                 List<Integer> closedList = new ArrayList<Integer>();
 470                 try (Resource r0 = createResource(0, bitMap, closedList);
 471                      Resource r1 = createResource(1, bitMap, closedList);
 472                      Resource r2 = createResource(2, bitMap, closedList)) {
 473                     if (failure != 0)
 474                         throw new MyKindOfException();
 475                 } catch (Resource.CreateFailException e) {
 476                     throw new AssertionError(
 477                                              "Resource creation failed: " + e.resourceId());
 478                 } catch (MyKindOfException e) {
 479                     if (failure == 0)
 480                         throw new AssertionError("Unexpected MyKindOfException");
 481                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 482                 } catch (Resource.CloseFailException e) {
 483                     if (failure == 1)
 484                         throw new AssertionError("Secondary exception suppression failed");
 485                     int id = e.resourceId();
 486                     if (bitMap == 0)
 487                         throw new AssertionError("Unexpected CloseFailException: " + id);
 488                     int highestCloseFailBit = Integer.highestOneBit(bitMap);
 489                     if (1 << id != highestCloseFailBit) {
 490                         throw new AssertionError("CloseFailException: got id " + id
 491                                                  + ", expected lg(" + highestCloseFailBit +")");
 492                     }
 493                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit);
 494                 }
 495                 checkClosedList(closedList, 3);
 496             }
 497         }
 498     }
 499 
 500     public static void testCreateSuccess3Nested() {
 501         for (int bitMap = 0, n = 1 << 3; bitMap < n; bitMap++) {
 502             for (int failure = 0; failure < 2; failure++) {
 503                 List<Integer> closedList = new ArrayList<Integer>();
 504                 try (Resource r0 = createResource(0, bitMap, closedList)) {
 505                     try (Resource r1 = createResource(1, bitMap, closedList)) {
 506                         try (Resource r2 = createResource(2, bitMap, closedList)) {
 507                             if (failure != 0)
 508                                 throw new MyKindOfException();
 509                         }
 510                     }
 511                 } catch (Resource.CreateFailException e) {
 512                     throw new AssertionError(
 513                                              "Resource creation failed: " + e.resourceId());
 514                 } catch (MyKindOfException e) {
 515                     if (failure == 0)
 516                         throw new AssertionError("Unexpected MyKindOfException");
 517                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 518                 } catch (Resource.CloseFailException e) {
 519                     if (failure == 1)
 520                         throw new AssertionError("Secondary exception suppression failed");
 521                     int id = e.resourceId();
 522                     if (bitMap == 0)
 523                         throw new AssertionError("Unexpected CloseFailException: " + id);
 524                     int highestCloseFailBit = Integer.highestOneBit(bitMap);
 525                     if (1 << id != highestCloseFailBit) {
 526                         throw new AssertionError("CloseFailException: got id " + id
 527                                                  + ", expected lg(" + highestCloseFailBit +")");
 528                     }
 529                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit);
 530                 }
 531                 checkClosedList(closedList, 3);
 532             }
 533         }
 534     }
 535 
 536     public static void testCreateSuccess4() {
 537         for (int bitMap = 0, n = 1 << 4; bitMap < n; bitMap++) {
 538             for (int failure = 0; failure < 2; failure++) {
 539                 List<Integer> closedList = new ArrayList<Integer>();
 540                 try (Resource r0 = createResource(0, bitMap, closedList);
 541                      Resource r1 = createResource(1, bitMap, closedList);
 542                      Resource r2 = createResource(2, bitMap, closedList);
 543                      Resource r3 = createResource(3, bitMap, closedList)) {
 544                     if (failure != 0)
 545                         throw new MyKindOfException();
 546                 } catch (Resource.CreateFailException e) {
 547                     throw new AssertionError(
 548                                              "Resource creation failed: " + e.resourceId());
 549                 } catch (MyKindOfException e) {
 550                     if (failure == 0)
 551                         throw new AssertionError("Unexpected MyKindOfException");
 552                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 553                 } catch (Resource.CloseFailException e) {
 554                     if (failure == 1)
 555                         throw new AssertionError("Secondary exception suppression failed");
 556                     int id = e.resourceId();
 557                     if (bitMap == 0)
 558                         throw new AssertionError("Unexpected CloseFailException: " + id);
 559                     int highestCloseFailBit = Integer.highestOneBit(bitMap);
 560                     if (1 << id != highestCloseFailBit) {
 561                         throw new AssertionError("CloseFailException: got id " + id
 562                                                  + ", expected lg(" + highestCloseFailBit +")");
 563                     }
 564                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit);
 565                 }
 566                 checkClosedList(closedList, 4);
 567             }
 568         }
 569     }
 570 
 571     public static void testCreateSuccess4Nested() {
 572         for (int bitMap = 0, n = 1 << 4; bitMap < n; bitMap++) {
 573             for (int failure = 0; failure < 2; failure++) {
 574                 List<Integer> closedList = new ArrayList<Integer>();
 575                 try (Resource r0 = createResource(0, bitMap, closedList)) {
 576                     try (Resource r1 = createResource(1, bitMap, closedList)) {
 577                         try (Resource r2 = createResource(2, bitMap, closedList)) {
 578                             try (Resource r3 = createResource(3, bitMap, closedList)) {
 579                                 if (failure != 0)
 580                                     throw new MyKindOfException();
 581                             }
 582                         }
 583                     }
 584                 } catch (Resource.CreateFailException e) {
 585                     throw new AssertionError(
 586                                              "Resource creation failed: " + e.resourceId());
 587                 } catch (MyKindOfException e) {
 588                     if (failure == 0)
 589                         throw new AssertionError("Unexpected MyKindOfException");
 590                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 591                 } catch (Resource.CloseFailException e) {
 592                     if (failure == 1)
 593                         throw new AssertionError("Secondary exception suppression failed");
 594                     int id = e.resourceId();
 595                     if (bitMap == 0)
 596                         throw new AssertionError("Unexpected CloseFailException: " + id);
 597                     int highestCloseFailBit = Integer.highestOneBit(bitMap);
 598                     if (1 << id != highestCloseFailBit) {
 599                         throw new AssertionError("CloseFailException: got id " + id
 600                                                  + ", expected lg(" + highestCloseFailBit +")");
 601                     }
 602                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit);
 603                 }
 604                 checkClosedList(closedList, 4);
 605             }
 606         }
 607     }
 608 
 609     public static void testCreateSuccess5() {
 610         for (int bitMap = 0, n = 1 << 5; bitMap < n; bitMap++) {
 611             for (int failure = 0; failure < 2; failure++) {
 612                 List<Integer> closedList = new ArrayList<Integer>();
 613                 try (Resource r0 = createResource(0, bitMap, closedList);
 614                      Resource r1 = createResource(1, bitMap, closedList);
 615                      Resource r2 = createResource(2, bitMap, closedList);
 616                      Resource r3 = createResource(3, bitMap, closedList);
 617                      Resource r4 = createResource(4, bitMap, closedList)) {
 618                     if (failure != 0)
 619                         throw new MyKindOfException();
 620                 } catch (Resource.CreateFailException e) {
 621                     throw new AssertionError("Resource creation failed: " + e.resourceId());
 622                 } catch (MyKindOfException e) {
 623                     if (failure == 0)
 624                         throw new AssertionError("Unexpected MyKindOfException");
 625                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 626                 } catch (Resource.CloseFailException e) {
 627                     if (failure == 1)
 628                         throw new AssertionError("Secondary exception suppression failed");
 629                     int id = e.resourceId();
 630                     if (bitMap == 0)
 631                         throw new AssertionError("Unexpected CloseFailException: " + id);
 632                     int highestCloseFailBit = Integer.highestOneBit(bitMap);
 633                     if (1 << id != highestCloseFailBit) {
 634                         throw new AssertionError("CloseFailException: got id " + id
 635                                                  + ", expected lg(" + highestCloseFailBit +")");
 636                     }
 637                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit);
 638                 }
 639                 checkClosedList(closedList, 5);
 640             }
 641         }
 642     }
 643 
 644     public static void testCreateSuccess5Nested() {
 645         for (int bitMap = 0, n = 1 << 5; bitMap < n; bitMap++) {
 646             for (int failure = 0; failure < 2; failure++) {
 647                 List<Integer> closedList = new ArrayList<Integer>();
 648                 try (Resource r0 = createResource(0, bitMap, closedList)) {
 649                     try (Resource r1 = createResource(1, bitMap, closedList)) {
 650                         try (Resource r2 = createResource(2, bitMap, closedList)) {
 651                             try (Resource r3 = createResource(3, bitMap, closedList)) {
 652                                 try (Resource r4 = createResource(4, bitMap, closedList)) {
 653                                     if (failure != 0)
 654                                         throw new MyKindOfException();
 655                                 }
 656                             }
 657                         }
 658                     }
 659                 } catch (Resource.CreateFailException e) {
 660                     throw new AssertionError("Resource creation failed: " + e.resourceId());
 661                 } catch (MyKindOfException e) {
 662                     if (failure == 0)
 663                         throw new AssertionError("Unexpected MyKindOfException");
 664                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 665                 } catch (Resource.CloseFailException e) {
 666                     if (failure == 1)
 667                         throw new AssertionError("Secondary exception suppression failed");
 668                     int id = e.resourceId();
 669                     if (bitMap == 0)
 670                         throw new AssertionError("Unexpected CloseFailException: " + id);
 671                     int highestCloseFailBit = Integer.highestOneBit(bitMap);
 672                     if (1 << id != highestCloseFailBit) {
 673                         throw new AssertionError("CloseFailException: got id " + id
 674                                                  + ", expected lg(" + highestCloseFailBit +")");
 675                     }
 676                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit);
 677                 }
 678                 checkClosedList(closedList, 5);
 679             }
 680         }
 681     }
 682 
 683     private static Resource createResource(int id,
 684                                            int closeFailureBitMap,
 685                                            List<Integer> closedList) throws Resource.CreateFailException {
 686         boolean closeSucceeds = (closeFailureBitMap & (1 << id)) == 0;
 687         return new Resource(id, true, closeSucceeds, closedList);
 688     }
 689 
 690     private static class MyKindOfException extends Exception {
 691     }
 692 }
 693 
 694 class Resource implements AutoCloseable {
 695     /** A number identifying this resource */
 696     private final int resourceId;
 697 
 698     /** Whether the close call on this resource should succeed or fail */
 699     private final boolean closeSucceeds;
 700 
 701     /** When resource is closed, it records its ID in this list */
 702     private final List<Integer> closedList;
 703 
 704     Resource(int resourceId, boolean createSucceeds, boolean closeSucceeds,
 705              List<Integer> closedList) throws CreateFailException {
 706         if (!createSucceeds)
 707             throw new CreateFailException(resourceId);
 708         this.resourceId = resourceId;
 709         this.closeSucceeds = closeSucceeds;
 710         this.closedList = closedList;
 711     }
 712 
 713     public void close() throws CloseFailException {
 714         closedList.add(resourceId);
 715         if (!closeSucceeds)
 716             throw new CloseFailException(resourceId);
 717     }
 718 
 719     public static class ResourceException extends RuntimeException {
 720         private final int resourceId;
 721 
 722         public ResourceException(int resourceId) {
 723             super("Resource ID = " + resourceId);
 724             this.resourceId = resourceId;
 725         }
 726 
 727         public int resourceId() {
 728             return resourceId;
 729         }
 730     }
 731 
 732     public static class CreateFailException extends ResourceException {
 733         public CreateFailException(int resourceId) {
 734             super(resourceId);
 735         }
 736     }
 737 
 738     public static class CloseFailException extends ResourceException {
 739         public CloseFailException(int resourceId) {
 740             super(resourceId);
 741         }
 742     }
 743 }