jdk/test/java/util/Objects/CheckIndex.java
changeset 37345 9cb6e1141bdb
parent 33844 c81ff6d8588d
child 38356 1e4ecca97792
equal deleted inserted replaced
37344:52d3d8517efc 37345:9cb6e1141bdb
    41 import static org.testng.Assert.*;
    41 import static org.testng.Assert.*;
    42 
    42 
    43 public class CheckIndex {
    43 public class CheckIndex {
    44 
    44 
    45     static class AssertingOutOfBoundsException extends RuntimeException {
    45     static class AssertingOutOfBoundsException extends RuntimeException {
    46     }
    46         public AssertingOutOfBoundsException(String message) {
    47 
    47             super(message);
    48     static BiFunction<Integer, Integer, AssertingOutOfBoundsException> assertingOutOfBounds(
    48         }
    49             int expFromIndex, int expToIndexOrSizeOrLength) {
    49     }
    50         return (fromIndex, toIndexOrSizeorLength) -> {
    50 
    51             assertEquals(fromIndex, Integer.valueOf(expFromIndex));
    51     static BiFunction<String, List<Integer>, AssertingOutOfBoundsException> assertingOutOfBounds(
    52             assertEquals(toIndexOrSizeorLength, Integer.valueOf(expToIndexOrSizeOrLength));
    52             String message, String expCheckKind, Integer... expArgs) {
    53             return new AssertingOutOfBoundsException();
    53         return (checkKind, args) -> {
    54         };
    54             assertEquals(checkKind, expCheckKind);
    55     }
    55             assertEquals(args, List.of(expArgs));
    56 
    56             try {
    57     static BiFunction<Integer, Integer, AssertingOutOfBoundsException> assertingOutOfBoundsReturnNull(
    57                 args.clear();
    58             int expFromIndex, int expToIndexOrSizeOrLength) {
    58                 fail("Out of bounds List<Integer> argument should be unmodifiable");
    59         return (fromIndex, toIndexOrSizeorLength) -> {
    59             } catch (Exception e)  {
    60             assertEquals(fromIndex, Integer.valueOf(expFromIndex));
    60             }
    61             assertEquals(toIndexOrSizeorLength, Integer.valueOf(expToIndexOrSizeOrLength));
    61             return new AssertingOutOfBoundsException(message);
       
    62         };
       
    63     }
       
    64 
       
    65     static BiFunction<String, List<Integer>, AssertingOutOfBoundsException> assertingOutOfBoundsReturnNull(
       
    66             String expCheckKind, Integer... expArgs) {
       
    67         return (checkKind, args) -> {
       
    68             assertEquals(checkKind, expCheckKind);
       
    69             assertEquals(args, List.of(expArgs));
    62             return null;
    70             return null;
    63         };
    71         };
    64     }
    72     }
    65 
    73 
    66     static final int[] VALUES = {0, 1, Integer.MAX_VALUE - 1, Integer.MAX_VALUE, -1, Integer.MIN_VALUE + 1, Integer.MIN_VALUE};
    74     static final int[] VALUES = {0, 1, Integer.MAX_VALUE - 1, Integer.MAX_VALUE, -1, Integer.MIN_VALUE + 1, Integer.MIN_VALUE};
    83         int apply(int a, int b, int c);
    91         int apply(int a, int b, int c);
    84     }
    92     }
    85 
    93 
    86     @Test(dataProvider = "checkIndexProvider")
    94     @Test(dataProvider = "checkIndexProvider")
    87     public void testCheckIndex(int index, int length, boolean withinBounds) {
    95     public void testCheckIndex(int index, int length, boolean withinBounds) {
    88         BiConsumer<Class<? extends RuntimeException>, IntSupplier> check = (ec, s) -> {
    96         String expectedMessage = withinBounds
       
    97                                  ? null
       
    98                                  : Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new).
       
    99                 apply("checkIndex", List.of(index, length)).getMessage();
       
   100 
       
   101         BiConsumer<Class<? extends RuntimeException>, IntSupplier> checker = (ec, s) -> {
    89             try {
   102             try {
    90                 int rIndex = s.getAsInt();
   103                 int rIndex = s.getAsInt();
    91                 if (!withinBounds)
   104                 if (!withinBounds)
    92                     fail(String.format(
   105                     fail(String.format(
    93                             "Index %d is out of bounds of [0, %d), but was reported to be within bounds", index, length));
   106                             "Index %d is out of bounds of [0, %d), but was reported to be within bounds", index, length));
    96             catch (RuntimeException e) {
   109             catch (RuntimeException e) {
    97                 assertTrue(ec.isInstance(e));
   110                 assertTrue(ec.isInstance(e));
    98                 if (withinBounds)
   111                 if (withinBounds)
    99                     fail(String.format(
   112                     fail(String.format(
   100                             "Index %d is within bounds of [0, %d), but was reported to be out of bounds", index, length));
   113                             "Index %d is within bounds of [0, %d), but was reported to be out of bounds", index, length));
   101             }
   114                 else
   102         };
   115                     assertEquals(e.getMessage(), expectedMessage);
   103 
   116             }
   104         check.accept(AssertingOutOfBoundsException.class,
   117         };
   105                      () -> Objects.checkIndex(index, length, assertingOutOfBounds(index, length)));
   118 
   106         check.accept(IndexOutOfBoundsException.class,
   119         checker.accept(AssertingOutOfBoundsException.class,
   107                      () -> Objects.checkIndex(index, length, assertingOutOfBoundsReturnNull(index, length)));
   120                      () -> Objects.checkIndex(index, length,
   108         check.accept(IndexOutOfBoundsException.class,
   121                                               assertingOutOfBounds(expectedMessage, "checkIndex", index, length)));
       
   122         checker.accept(IndexOutOfBoundsException.class,
       
   123                      () -> Objects.checkIndex(index, length,
       
   124                                               assertingOutOfBoundsReturnNull("checkIndex", index, length)));
       
   125         checker.accept(IndexOutOfBoundsException.class,
   109                      () -> Objects.checkIndex(index, length, null));
   126                      () -> Objects.checkIndex(index, length, null));
   110         check.accept(IndexOutOfBoundsException.class,
   127         checker.accept(IndexOutOfBoundsException.class,
   111                      () -> Objects.checkIndex(index, length));
   128                      () -> Objects.checkIndex(index, length));
       
   129         checker.accept(ArrayIndexOutOfBoundsException.class,
       
   130                      () -> Objects.checkIndex(index, length,
       
   131                                               Objects.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new)));
       
   132         checker.accept(StringIndexOutOfBoundsException.class,
       
   133                      () -> Objects.checkIndex(index, length,
       
   134                                               Objects.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new)));
   112     }
   135     }
   113 
   136 
   114 
   137 
   115     @DataProvider
   138     @DataProvider
   116     static Object[][] checkFromToIndexProvider() {
   139     static Object[][] checkFromToIndexProvider() {
   130         return l.toArray(new Object[0][0]);
   153         return l.toArray(new Object[0][0]);
   131     }
   154     }
   132 
   155 
   133     @Test(dataProvider = "checkFromToIndexProvider")
   156     @Test(dataProvider = "checkFromToIndexProvider")
   134     public void testCheckFromToIndex(int fromIndex, int toIndex, int length, boolean withinBounds) {
   157     public void testCheckFromToIndex(int fromIndex, int toIndex, int length, boolean withinBounds) {
       
   158         String expectedMessage = withinBounds
       
   159                                  ? null
       
   160                                  : Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new).
       
   161                 apply("checkFromToIndex", List.of(fromIndex, toIndex, length)).getMessage();
       
   162 
   135         BiConsumer<Class<? extends RuntimeException>, IntSupplier> check = (ec, s) -> {
   163         BiConsumer<Class<? extends RuntimeException>, IntSupplier> check = (ec, s) -> {
   136             try {
   164             try {
   137                 int rIndex = s.getAsInt();
   165                 int rIndex = s.getAsInt();
   138                 if (!withinBounds)
   166                 if (!withinBounds)
   139                     fail(String.format(
   167                     fail(String.format(
   143             catch (RuntimeException e) {
   171             catch (RuntimeException e) {
   144                 assertTrue(ec.isInstance(e));
   172                 assertTrue(ec.isInstance(e));
   145                 if (withinBounds)
   173                 if (withinBounds)
   146                     fail(String.format(
   174                     fail(String.format(
   147                             "Range [%d, %d) is within bounds of [0, %d), but was reported to be out of bounds", fromIndex, toIndex, length));
   175                             "Range [%d, %d) is within bounds of [0, %d), but was reported to be out of bounds", fromIndex, toIndex, length));
       
   176                 else
       
   177                     assertEquals(e.getMessage(), expectedMessage);
   148             }
   178             }
   149         };
   179         };
   150 
   180 
   151         check.accept(AssertingOutOfBoundsException.class,
   181         check.accept(AssertingOutOfBoundsException.class,
   152                      () -> Objects.checkFromToIndex(fromIndex, toIndex, length, assertingOutOfBounds(fromIndex, toIndex)));
   182                      () -> Objects.checkFromToIndex(fromIndex, toIndex, length,
   153         check.accept(IndexOutOfBoundsException.class,
   183                                                     assertingOutOfBounds(expectedMessage, "checkFromToIndex", fromIndex, toIndex, length)));
   154                      () -> Objects.checkFromToIndex(fromIndex, toIndex, length, assertingOutOfBoundsReturnNull(fromIndex, toIndex)));
   184         check.accept(IndexOutOfBoundsException.class,
       
   185                      () -> Objects.checkFromToIndex(fromIndex, toIndex, length,
       
   186                                                     assertingOutOfBoundsReturnNull("checkFromToIndex", fromIndex, toIndex, length)));
   155         check.accept(IndexOutOfBoundsException.class,
   187         check.accept(IndexOutOfBoundsException.class,
   156                      () -> Objects.checkFromToIndex(fromIndex, toIndex, length, null));
   188                      () -> Objects.checkFromToIndex(fromIndex, toIndex, length, null));
   157         check.accept(IndexOutOfBoundsException.class,
   189         check.accept(IndexOutOfBoundsException.class,
   158                      () -> Objects.checkFromToIndex(fromIndex, toIndex, length));
   190                      () -> Objects.checkFromToIndex(fromIndex, toIndex, length));
       
   191         check.accept(ArrayIndexOutOfBoundsException.class,
       
   192                      () -> Objects.checkFromToIndex(fromIndex, toIndex, length,
       
   193                                               Objects.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new)));
       
   194         check.accept(StringIndexOutOfBoundsException.class,
       
   195                      () -> Objects.checkFromToIndex(fromIndex, toIndex, length,
       
   196                                               Objects.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new)));
   159     }
   197     }
   160 
   198 
   161 
   199 
   162     @DataProvider
   200     @DataProvider
   163     static Object[][] checkFromIndexSizeProvider() {
   201     static Object[][] checkFromIndexSizeProvider() {
   184         return l.toArray(new Object[0][0]);
   222         return l.toArray(new Object[0][0]);
   185     }
   223     }
   186 
   224 
   187     @Test(dataProvider = "checkFromIndexSizeProvider")
   225     @Test(dataProvider = "checkFromIndexSizeProvider")
   188     public void testCheckFromIndexSize(int fromIndex, int size, int length, boolean withinBounds) {
   226     public void testCheckFromIndexSize(int fromIndex, int size, int length, boolean withinBounds) {
       
   227         String expectedMessage = withinBounds
       
   228                                  ? null
       
   229                                  : Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new).
       
   230                 apply("checkFromIndexSize", List.of(fromIndex, size, length)).getMessage();
       
   231 
   189         BiConsumer<Class<? extends RuntimeException>, IntSupplier> check = (ec, s) -> {
   232         BiConsumer<Class<? extends RuntimeException>, IntSupplier> check = (ec, s) -> {
   190             try {
   233             try {
   191                 int rIndex = s.getAsInt();
   234                 int rIndex = s.getAsInt();
   192                 if (!withinBounds)
   235                 if (!withinBounds)
   193                     fail(String.format(
   236                     fail(String.format(
   197             catch (RuntimeException e) {
   240             catch (RuntimeException e) {
   198                 assertTrue(ec.isInstance(e));
   241                 assertTrue(ec.isInstance(e));
   199                 if (withinBounds)
   242                 if (withinBounds)
   200                     fail(String.format(
   243                     fail(String.format(
   201                             "Range [%d, %d + %d) is within bounds of [0, %d), but was reported to be out of bounds", fromIndex, fromIndex, size, length));
   244                             "Range [%d, %d + %d) is within bounds of [0, %d), but was reported to be out of bounds", fromIndex, fromIndex, size, length));
       
   245                 else
       
   246                     assertEquals(e.getMessage(), expectedMessage);
   202             }
   247             }
   203         };
   248         };
   204 
   249 
   205         check.accept(AssertingOutOfBoundsException.class,
   250         check.accept(AssertingOutOfBoundsException.class,
   206                      () -> Objects.checkFromIndexSize(fromIndex, size, length, assertingOutOfBounds(fromIndex, size)));
   251                      () -> Objects.checkFromIndexSize(fromIndex, size, length,
   207         check.accept(IndexOutOfBoundsException.class,
   252                                                       assertingOutOfBounds(expectedMessage, "checkFromIndexSize", fromIndex, size, length)));
   208                      () -> Objects.checkFromIndexSize(fromIndex, size, length, assertingOutOfBoundsReturnNull(fromIndex, size)));
   253         check.accept(IndexOutOfBoundsException.class,
       
   254                      () -> Objects.checkFromIndexSize(fromIndex, size, length,
       
   255                                                       assertingOutOfBoundsReturnNull("checkFromIndexSize", fromIndex, size, length)));
   209         check.accept(IndexOutOfBoundsException.class,
   256         check.accept(IndexOutOfBoundsException.class,
   210                      () -> Objects.checkFromIndexSize(fromIndex, size, length, null));
   257                      () -> Objects.checkFromIndexSize(fromIndex, size, length, null));
   211         check.accept(IndexOutOfBoundsException.class,
   258         check.accept(IndexOutOfBoundsException.class,
   212                      () -> Objects.checkFromIndexSize(fromIndex, size, length));
   259                      () -> Objects.checkFromIndexSize(fromIndex, size, length));
       
   260         check.accept(ArrayIndexOutOfBoundsException.class,
       
   261                      () -> Objects.checkFromIndexSize(fromIndex, size, length,
       
   262                                                     Objects.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new)));
       
   263         check.accept(StringIndexOutOfBoundsException.class,
       
   264                      () -> Objects.checkFromIndexSize(fromIndex, size, length,
       
   265                                                     Objects.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new)));
   213     }
   266     }
   214 
   267 
   215     @Test
   268     @Test
   216     public void checkIndexOutOfBoundsExceptionConstructors() {
   269     public void uniqueMessagesForCheckKinds() {
   217         BiConsumer<Class<? extends RuntimeException>, IntSupplier> check = (ec, s) -> {
   270         BiFunction<String, List<Integer>, IndexOutOfBoundsException> f =
   218             try {
   271                 Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new);
   219                 s.getAsInt();
   272 
   220                 fail("Runtime exception expected");
   273         List<String> messages = new ArrayList<>();
   221             }
   274         // Exact arguments
   222             catch (RuntimeException e) {
   275         messages.add(f.apply("checkIndex", List.of(-1, 0)).getMessage());
   223                 assertTrue(ec.isInstance(e));
   276         messages.add(f.apply("checkFromToIndex", List.of(-1, 0, 0)).getMessage());
   224             }
   277         messages.add(f.apply("checkFromIndexSize", List.of(-1, 0, 0)).getMessage());
   225         };
   278         // Unknown check kind
   226 
   279         messages.add(f.apply("checkUnknown", List.of(-1, 0, 0)).getMessage());
   227         check.accept(IndexOutOfBoundsException.class,
   280         // Known check kind with more arguments
   228                      () -> Objects.checkIndex(1, 0, IndexOutOfBoundsException::new));
   281         messages.add(f.apply("checkIndex", List.of(-1, 0, 0)).getMessage());
   229         check.accept(StringIndexOutOfBoundsException.class,
   282         messages.add(f.apply("checkFromToIndex", List.of(-1, 0, 0, 0)).getMessage());
   230                      () -> Objects.checkIndex(1, 0, StringIndexOutOfBoundsException::new));
   283         messages.add(f.apply("checkFromIndexSize", List.of(-1, 0, 0, 0)).getMessage());
   231         check.accept(ArrayIndexOutOfBoundsException.class,
   284         // Known check kind with fewer arguments
   232                      () -> Objects.checkIndex(1, 0, ArrayIndexOutOfBoundsException::new));
   285         messages.add(f.apply("checkIndex", List.of(-1)).getMessage());
       
   286         messages.add(f.apply("checkFromToIndex", List.of(-1, 0)).getMessage());
       
   287         messages.add(f.apply("checkFromIndexSize", List.of(-1, 0)).getMessage());
       
   288         // Null arguments
       
   289         messages.add(f.apply(null, null).getMessage());
       
   290         messages.add(f.apply("checkNullArguments", null).getMessage());
       
   291         messages.add(f.apply(null, List.of(-1)).getMessage());
       
   292 
       
   293         assertEquals(messages.size(), messages.stream().distinct().count());
   233     }
   294     }
   234 }
   295 }