1 /*
   2  * Copyright (c) 2009, 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
  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         testCreateFailure3();
  38         testCreateFailure4();
  39         testCreateFailure5();
  40 
  41         testCreateSuccess1();
  42         testCreateSuccess2();
  43         testCreateSuccess3();
  44         testCreateSuccess4();
  45         testCreateSuccess5();
  46     }
  47 
  48     /*
  49      * The following tests simulate a creation failure of every possible
  50      * resource in an ARM block, and check to make sure that the failure
  51      * prevents creation of subsequent resources, and that all created
  52      * resources are properly closed, even if one or more of the close
  53      * attempts fails.
  54      */
  55 
  56     public static void testCreateFailure1() {
  57         int creationFailuresDetected = 0;
  58         List<Integer> closedList = new ArrayList<Integer>(0);
  59         try (Resource r0 = createResource(0, 0, 0, closedList)) {
  60             throw new AssertionError("Resource creation succeeded");
  61         } catch (Resource.CreateFailException e) {
  62             creationFailuresDetected++;
  63             if (e.resourceId() != 0) {
  64                 throw new AssertionError("Wrong resource creation "
  65                                          + e.resourceId() + " failed");
  66             }
  67         } catch (Resource.CloseFailException e) {
  68             throw new AssertionError("Unexpected CloseFailException: " + e.resourceId());
  69         }
  70         checkForSingleCreationFailure(creationFailuresDetected);
  71         checkClosedList(closedList, 0);
  72     }
  73 
  74     public static void testCreateFailure2() {
  75         for (int createFailureId = 0; createFailureId < 2; createFailureId++) {
  76             for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) {
  77                 int creationFailuresDetected = 0;
  78                 List<Integer> closedList = new ArrayList<Integer>();
  79                 try (Resource r0 = createResource(0, createFailureId, bitMap, closedList);
  80                      Resource r1 = createResource(1, createFailureId, bitMap, closedList)) {
  81                     throw new AssertionError("Entire resource creation succeeded");
  82                 } catch (Resource.CreateFailException e) {
  83                     creationFailuresDetected++;
  84                     checkCreateFailureId(e.resourceId(), createFailureId);
  85                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
  86                 } catch (Resource.CloseFailException e) {
  87                     throw new AssertionError("Secondary exception suppression failed");
  88                 }
  89                 checkForSingleCreationFailure(creationFailuresDetected);
  90                 checkClosedList(closedList, createFailureId);
  91             }
  92         }
  93     }
  94 
  95     public static void testCreateFailure3() {
  96         for (int createFailureId = 0; createFailureId < 3; createFailureId++) {
  97             for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) {
  98                 int creationFailuresDetected = 0;
  99                 List<Integer> closedList = new ArrayList<Integer>();
 100                 try (Resource r0 = createResource(0, createFailureId, bitMap, closedList);
 101                      Resource r1 = createResource(1, createFailureId, bitMap, closedList);
 102                      Resource r2 = createResource(2, createFailureId, bitMap, closedList)) {
 103                     throw new AssertionError("Entire resource creation succeeded");
 104                 } catch (Resource.CreateFailException e) {
 105                     creationFailuresDetected++;
 106                     checkCreateFailureId(e.resourceId(), createFailureId);
 107                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 108                 } catch (Resource.CloseFailException e) {
 109                     throw new AssertionError("Secondary exception suppression failed:" + e);
 110                 }
 111                 checkForSingleCreationFailure(creationFailuresDetected);
 112                 checkClosedList(closedList, createFailureId);
 113             }
 114         }
 115     }
 116 
 117     public static void testCreateFailure4() {
 118         for (int createFailureId = 0; createFailureId < 4; createFailureId++) {
 119             for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) {
 120                 int creationFailuresDetected = 0;
 121                 List<Integer> closedList = new ArrayList<Integer>();
 122                 try (Resource r0 = createResource(0, createFailureId, bitMap, closedList);
 123                      Resource r1 = createResource(1, createFailureId, bitMap, closedList);
 124                      Resource r2 = createResource(2, createFailureId, bitMap, closedList);
 125                      Resource r3 = createResource(3, createFailureId, bitMap, closedList)) {
 126                     throw new AssertionError("Entire resource creation succeeded");
 127                 } catch (Resource.CreateFailException e) {
 128                     creationFailuresDetected++;
 129                     checkCreateFailureId(e.resourceId(), createFailureId);
 130                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 131                 } catch (Resource.CloseFailException e) {
 132                     throw new AssertionError("Secondary exception suppression failed:" + e);
 133                 }
 134                 checkForSingleCreationFailure(creationFailuresDetected);
 135                 checkClosedList(closedList, createFailureId);
 136             }
 137         }
 138     }
 139 
 140     public static void testCreateFailure5() {
 141         for (int createFailureId = 0; createFailureId < 5; createFailureId++) {
 142             for (int bitMap = 0, n = 1 << createFailureId; bitMap < n; bitMap++) {
 143                 int creationFailuresDetected = 0;
 144                 List<Integer> closedList = new ArrayList<Integer>();
 145                 try (Resource r0 = createResource(0, createFailureId, bitMap, closedList);
 146                      Resource r1 = createResource(1, createFailureId, bitMap, closedList);
 147                      Resource r2 = createResource(2, createFailureId, bitMap, closedList);
 148                      Resource r3 = createResource(3, createFailureId, bitMap, closedList);
 149                      Resource r4 = createResource(4, createFailureId, bitMap, closedList)) {
 150                     throw new AssertionError("Entire resource creation succeeded");
 151                 } catch (Resource.CreateFailException e) {
 152                     creationFailuresDetected++;
 153                     checkCreateFailureId(e.resourceId(), createFailureId);
 154                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 155                 } catch (Resource.CloseFailException e) {
 156                     throw new AssertionError("Secondary exception suppression failed:" + e);
 157                 }
 158                 checkForSingleCreationFailure(creationFailuresDetected);
 159                 checkClosedList(closedList, createFailureId);
 160             }
 161         }
 162     }
 163 
 164     /**
 165      * Create a resource with the specified ID. The ID must be less than createFailureId.
 166      * A subsequent attempt to close the resource will fail iff the corresponding bit
 167      * is set in closeFailureBitMap.  When an attempt is made to close this resource,
 168      * its ID will be added to closedList, regardless of whether the attempt succeeds.
 169      *
 170      * @param id the ID of this resource
 171      * @param createFailureId the ID of the resource whose creation will fail
 172      * @param closeFailureBitMap a bit vector describing which resources should throw an 
 173      *        exception when close is attempted
 174      * @param closedList a list on which to record resource close attempts
 175      * @throws AssertionError if no attempt should be made to create this resource
 176      */
 177     private static Resource createResource(int id,
 178                                            int createFailureId,
 179                                            int closeFailureBitMap,
 180                                            List<Integer> closedList) throws Resource.CreateFailException {
 181         if (id > createFailureId)
 182             throw new AssertionError("Resource " + id + " shouldn't be created");
 183         boolean createSucceeds = id != createFailureId;
 184         boolean closeSucceeds = (closeFailureBitMap & (1 << id)) == 0;
 185         return new Resource(id, createSucceeds, closeSucceeds, closedList);
 186     }
 187 
 188 
 189     /**
 190      * Check that an observed creation failure has the expected resource ID.
 191      *
 192      * @param foundId the ID of the resource whose creation failed
 193      * @param expectedId the ID of the resource whose creation should have failed
 194      */
 195     private static void checkCreateFailureId(int foundId, int expectedId) {
 196         if (foundId != expectedId)
 197             throw new AssertionError("Wrong resource creation failed. Found ID "
 198                                      + foundId + " expected " + expectedId);
 199     }
 200 
 201     /**
 202      * Check for proper suppressed exceptions in proper order.
 203      *
 204      * @param suppressedExceptions the suppressed exceptions array returned by
 205      *        getSuppressedExceptions()
 206      * @bitmap a bitmap indicating which suppressed exceptions are expected.
 207      *         Bit i is set iff id should throw a CloseFailException.
 208      */
 209     private static void checkSuppressedExceptions(Throwable[] suppressedExceptions, int bitMap) {
 210         if (suppressedExceptions.length != Integer.bitCount(bitMap))
 211             throw new AssertionError("Expected " + Integer.bitCount(bitMap)
 212                                      + " suppressed exceptions, got " +  suppressedExceptions.length);
 213 
 214         int prevCloseFailExceptionId = Integer.MAX_VALUE;
 215         for (Throwable t : suppressedExceptions) {
 216             int id = ((Resource.CloseFailException) t).resourceId();
 217             if ((1 << id  & bitMap) == 0)
 218                 throw new AssertionError("Unexpected suppressed CloseFailException: " + id);
 219             if (id > prevCloseFailExceptionId)
 220                 throw new AssertionError("Suppressed CloseFailException" + id
 221                                          + " followed " + prevCloseFailExceptionId);
 222         }
 223     }
 224 
 225     /**
 226      * Check that exactly one resource creation failed.
 227      * 
 228      * @param numCreationFailuresDetected the number of creation failures detected
 229      */
 230     private static void checkForSingleCreationFailure(int numCreationFailuresDetected) {
 231         if (numCreationFailuresDetected != 1)
 232             throw new AssertionError("Wrong number of creation failures: "
 233                                      + numCreationFailuresDetected);
 234     }
 235 
 236     /**
 237      * Check that a close was attempted on every resourced that was successfully opened,
 238      * and that the close attempts occurred in the proper order.
 239      * 
 240      * @param closedList the resource IDs of the close attempts, in the order they occurred
 241      * @param the ID of the resource whose creation failed.  Close attempts should occur
 242      *        for all previous resources, in reverse order.
 243      *        
 244      */
 245     private static void checkClosedList(List<Integer> closedList, int createFailureId) {
 246         List<Integer> expectedList = new ArrayList<Integer>(createFailureId);
 247         for (int i = createFailureId - 1; i >= 0; i--)
 248             expectedList.add(i);
 249         if (!closedList.equals(expectedList))
 250             throw new AssertionError("Closing sequence " + closedList + " != " + expectedList);
 251     }
 252 
 253     /*
 254      * The following tests simulate the creation of several resources, followed
 255      * by success or failure of forward processing.  They test that all resources
 256      * are properly closed, even if one or more of the close attempts fails.
 257      */
 258 
 259     public static void testCreateSuccess1() {
 260         for (int bitMap = 0, n = 1 << 1; bitMap < n; bitMap++) {
 261             for (int failure = 0; failure < 2; failure++) {
 262                 List<Integer> closedList = new ArrayList<Integer>();
 263                 try (Resource r0 = createResource(0, bitMap, closedList)) {
 264                     if (failure != 0)
 265                         throw new MyKindOfException();
 266                 } catch (Resource.CreateFailException e) {
 267                     throw new AssertionError(
 268                                              "Resource creation failed: " + e.resourceId());
 269                 } catch (MyKindOfException e) {
 270                     if (failure == 0)
 271                         throw new AssertionError("Unexpected MyKindOfException");
 272                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 273                 } catch (Resource.CloseFailException e) {
 274                     if (failure == 1)
 275                         throw new AssertionError("Secondary exception suppression failed");
 276                     int id = e.resourceId();
 277                     if (bitMap == 0)
 278                         throw new AssertionError("Unexpected CloseFailException: " + id);
 279                     int highestCloseFailBit = Integer.highestOneBit(bitMap);
 280                     if (1 << id != highestCloseFailBit) {
 281                         throw new AssertionError("CloseFailException: got id " + id
 282                                                  + ", expected lg(" + highestCloseFailBit +")");
 283                     }
 284                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit);
 285                 }
 286                 checkClosedList(closedList, 1);
 287             }
 288         }
 289     }
 290 
 291     public static void testCreateSuccess2() {
 292         for (int bitMap = 0, n = 1 << 2; bitMap < n; bitMap++) {
 293             for (int failure = 0; failure < 2; failure++) {
 294                 List<Integer> closedList = new ArrayList<Integer>();
 295                 try (Resource r0 = createResource(0, bitMap, closedList);
 296                      Resource r1 = createResource(1, bitMap, closedList)) {
 297                     if (failure != 0)
 298                         throw new MyKindOfException();
 299                 } catch (Resource.CreateFailException e) {
 300                     throw new AssertionError(
 301                                              "Resource creation failed: " + e.resourceId());
 302                 } catch (MyKindOfException e) {
 303                     if (failure == 0)
 304                         throw new AssertionError("Unexpected MyKindOfException");
 305                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 306                 } catch (Resource.CloseFailException e) {
 307                     if (failure == 1)
 308                         throw new AssertionError("Secondary exception suppression failed");
 309                     int id = e.resourceId();
 310                     if (bitMap == 0)
 311                         throw new AssertionError("Unexpected CloseFailException: " + id);
 312                     int highestCloseFailBit = Integer.highestOneBit(bitMap);
 313                     if (1 << id != highestCloseFailBit) {
 314                         throw new AssertionError("CloseFailException: got id " + id
 315                                                  + ", expected lg(" + highestCloseFailBit +")");
 316                     }
 317                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit);
 318                 }
 319                 checkClosedList(closedList, 2);
 320             }
 321         }
 322     }
 323 
 324     public static void testCreateSuccess3() {
 325         for (int bitMap = 0, n = 1 << 3; bitMap < n; bitMap++) {
 326             for (int failure = 0; failure < 2; failure++) {
 327                 List<Integer> closedList = new ArrayList<Integer>();
 328                 try (Resource r0 = createResource(0, bitMap, closedList);
 329                      Resource r1 = createResource(1, bitMap, closedList);
 330                      Resource r2 = createResource(2, bitMap, closedList)) {
 331                     if (failure != 0)
 332                         throw new MyKindOfException();
 333                 } catch (Resource.CreateFailException e) {
 334                     throw new AssertionError(
 335                                              "Resource creation failed: " + e.resourceId());
 336                 } catch (MyKindOfException e) {
 337                     if (failure == 0)
 338                         throw new AssertionError("Unexpected MyKindOfException");
 339                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 340                 } catch (Resource.CloseFailException e) {
 341                     if (failure == 1)
 342                         throw new AssertionError("Secondary exception suppression failed");
 343                     int id = e.resourceId();
 344                     if (bitMap == 0)
 345                         throw new AssertionError("Unexpected CloseFailException: " + id);
 346                     int highestCloseFailBit = Integer.highestOneBit(bitMap);
 347                     if (1 << id != highestCloseFailBit) {
 348                         throw new AssertionError("CloseFailException: got id " + id
 349                                                  + ", expected lg(" + highestCloseFailBit +")");
 350                     }
 351                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit);
 352                 }
 353                 checkClosedList(closedList, 3);
 354             }
 355         }
 356     }
 357 
 358     public static void testCreateSuccess4() {
 359         for (int bitMap = 0, n = 1 << 4; bitMap < n; bitMap++) {
 360             for (int failure = 0; failure < 2; failure++) {
 361                 List<Integer> closedList = new ArrayList<Integer>();
 362                 try (Resource r0 = createResource(0, bitMap, closedList);
 363                      Resource r1 = createResource(1, bitMap, closedList);
 364                      Resource r2 = createResource(2, bitMap, closedList);
 365                      Resource r3 = createResource(3, bitMap, closedList)) {
 366                     if (failure != 0)
 367                         throw new MyKindOfException();
 368                 } catch (Resource.CreateFailException e) {
 369                     throw new AssertionError(
 370                                              "Resource creation failed: " + e.resourceId());
 371                 } catch (MyKindOfException e) {
 372                     if (failure == 0)
 373                         throw new AssertionError("Unexpected MyKindOfException");
 374                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 375                 } catch (Resource.CloseFailException e) {
 376                     if (failure == 1)
 377                         throw new AssertionError("Secondary exception suppression failed");
 378                     int id = e.resourceId();
 379                     if (bitMap == 0)
 380                         throw new AssertionError("Unexpected CloseFailException: " + id);
 381                     int highestCloseFailBit = Integer.highestOneBit(bitMap);
 382                     if (1 << id != highestCloseFailBit) {
 383                         throw new AssertionError("CloseFailException: got id " + id
 384                                                  + ", expected lg(" + highestCloseFailBit +")");
 385                     }
 386                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit);
 387                 }
 388                 checkClosedList(closedList, 4);
 389             }
 390         }
 391     }
 392 
 393     public static void testCreateSuccess5() {
 394         for (int bitMap = 0, n = 1 << 5; bitMap < n; bitMap++) {
 395             for (int failure = 0; failure < 2; failure++) {
 396                 List<Integer> closedList = new ArrayList<Integer>();
 397                 try (Resource r0 = createResource(0, bitMap, closedList);
 398                      Resource r1 = createResource(1, bitMap, closedList);
 399                      Resource r2 = createResource(2, bitMap, closedList);
 400                      Resource r3 = createResource(3, bitMap, closedList);
 401                      Resource r4 = createResource(4, bitMap, closedList)) {
 402                     if (failure != 0)
 403                         throw new MyKindOfException();
 404                 } catch (Resource.CreateFailException e) {
 405                     throw new AssertionError("Resource creation failed: " + e.resourceId());
 406                 } catch (MyKindOfException e) {
 407                     if (failure == 0)
 408                         throw new AssertionError("Unexpected MyKindOfException");
 409                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap);
 410                 } catch (Resource.CloseFailException e) {
 411                     if (failure == 1)
 412                         throw new AssertionError("Secondary exception suppression failed");
 413                     int id = e.resourceId();
 414                     if (bitMap == 0)
 415                         throw new AssertionError("Unexpected CloseFailException: " + id);
 416                     int highestCloseFailBit = Integer.highestOneBit(bitMap);
 417                     if (1 << id != highestCloseFailBit) {
 418                         throw new AssertionError("CloseFailException: got id " + id
 419                                                  + ", expected lg(" + highestCloseFailBit +")");
 420                     }
 421                     checkSuppressedExceptions(e.getSuppressedExceptions(), bitMap & ~highestCloseFailBit);
 422                 }
 423                 checkClosedList(closedList, 5);
 424             }
 425         }
 426     }
 427 
 428     private static Resource createResource(int id,
 429                                            int closeFailureBitMap,
 430                                            List<Integer> closedList) throws Resource.CreateFailException {
 431         boolean closeSucceeds = (closeFailureBitMap & (1 << id)) == 0;
 432         return new Resource(id, true, closeSucceeds, closedList);
 433     }
 434 
 435     private static class MyKindOfException extends Exception {
 436     }
 437 }
 438 
 439 class Resource implements AutoCloseable {
 440     /** A number identifying this resource */
 441     private final int resourceId;
 442 
 443     /** Whether the close call on this resource should succeed or fail */
 444     private final boolean closeSucceeds;
 445 
 446     /** When resource is closed, it records its ID in this list */
 447     private final List<Integer> closedList;
 448 
 449     Resource(int resourceId, boolean createSucceeds, boolean closeSucceeds,
 450              List<Integer> closedList) throws CreateFailException {
 451         if (!createSucceeds)
 452             throw new CreateFailException(resourceId);
 453         this.resourceId = resourceId;
 454         this.closeSucceeds = closeSucceeds;
 455         this.closedList = closedList;
 456     }
 457 
 458     public void close() throws CloseFailException {
 459         closedList.add(resourceId);
 460         if (!closeSucceeds)
 461             throw new CloseFailException(resourceId);
 462     }
 463 
 464     public static class ResourceException extends RuntimeException {
 465         private final int resourceId;
 466 
 467         public ResourceException(int resourceId) {
 468             super("Resource ID = " + resourceId);
 469             this.resourceId = resourceId;
 470         }
 471 
 472         public int resourceId() {
 473             return resourceId;
 474         }
 475     }
 476 
 477     public static class CreateFailException extends ResourceException {
 478         public CreateFailException(int resourceId) {
 479             super(resourceId);
 480         }
 481     }
 482 
 483     public static class CloseFailException extends ResourceException {
 484         public CloseFailException(int resourceId) {
 485             super(resourceId);
 486         }
 487     }
 488 }