Path: blob/master/test/jdk/java/util/Objects/CheckIndex.java
41149 views
/*1* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @summary Objects.checkIndex/jdk.internal.util.Preconditions.checkIndex tests for int values26* @run testng CheckIndex27* @bug 8135248 8142493 815579428* @modules java.base/jdk.internal.util29*/3031import jdk.internal.util.Preconditions;32import org.testng.annotations.DataProvider;33import org.testng.annotations.Test;3435import java.util.ArrayList;36import java.util.List;37import java.util.Objects;38import java.util.function.BiConsumer;39import java.util.function.BiFunction;40import java.util.function.IntSupplier;4142import static org.testng.Assert.*;4344public class CheckIndex {4546static class AssertingOutOfBoundsException extends RuntimeException {47public AssertingOutOfBoundsException(String message) {48super(message);49}50}5152static BiFunction<String, List<Number>, AssertingOutOfBoundsException> assertingOutOfBounds(53String message, String expCheckKind, Integer... expArgs) {54return (checkKind, args) -> {55assertEquals(checkKind, expCheckKind);56assertEquals(args, List.of(expArgs));57try {58args.clear();59fail("Out of bounds List<Integer> argument should be unmodifiable");60} catch (Exception e) {61}62return new AssertingOutOfBoundsException(message);63};64}6566static BiFunction<String, List<Number>, AssertingOutOfBoundsException> assertingOutOfBoundsReturnNull(67String expCheckKind, Integer... expArgs) {68return (checkKind, args) -> {69assertEquals(checkKind, expCheckKind);70assertEquals(args, List.of(expArgs));71return null;72};73}7475static final int[] VALUES = {0, 1, Integer.MAX_VALUE - 1, Integer.MAX_VALUE, -1, Integer.MIN_VALUE + 1, Integer.MIN_VALUE};7677@DataProvider78static Object[][] checkIndexProvider() {79List<Object[]> l = new ArrayList<>();80for (int index : VALUES) {81for (int length : VALUES) {82boolean withinBounds = index >= 0 &&83length >= 0 &&84index < length;85l.add(new Object[]{index, length, withinBounds});86}87}88return l.toArray(Object[][]::new);89}9091@Test(dataProvider = "checkIndexProvider")92public void testCheckIndex(int index, int length, boolean withinBounds) {93String expectedMessage = withinBounds94? null95: Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new).96apply("checkIndex", List.of(index, length)).getMessage();9798BiConsumer<Class<? extends RuntimeException>, IntSupplier> checker = (ec, s) -> {99try {100int rIndex = s.getAsInt();101if (!withinBounds)102fail(String.format(103"Index %d is out of bounds of [0, %d), but was reported to be within bounds", index, length));104assertEquals(rIndex, index);105}106catch (RuntimeException e) {107assertTrue(ec.isInstance(e));108if (withinBounds)109fail(String.format(110"Index %d is within bounds of [0, %d), but was reported to be out of bounds", index, length));111else112assertEquals(e.getMessage(), expectedMessage);113}114};115116checker.accept(AssertingOutOfBoundsException.class,117() -> Preconditions.checkIndex(index, length,118assertingOutOfBounds(expectedMessage, "checkIndex", index, length)));119checker.accept(IndexOutOfBoundsException.class,120() -> Preconditions.checkIndex(index, length,121assertingOutOfBoundsReturnNull("checkIndex", index, length)));122checker.accept(IndexOutOfBoundsException.class,123() -> Preconditions.checkIndex(index, length, null));124checker.accept(IndexOutOfBoundsException.class,125() -> Objects.checkIndex(index, length));126checker.accept(ArrayIndexOutOfBoundsException.class,127() -> Preconditions.checkIndex(index, length,128Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new)));129checker.accept(StringIndexOutOfBoundsException.class,130() -> Preconditions.checkIndex(index, length,131Preconditions.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new)));132}133134135@DataProvider136static Object[][] checkFromToIndexProvider() {137List<Object[]> l = new ArrayList<>();138for (int fromIndex : VALUES) {139for (int toIndex : VALUES) {140for (int length : VALUES) {141boolean withinBounds = fromIndex >= 0 &&142toIndex >= 0 &&143length >= 0 &&144fromIndex <= toIndex &&145toIndex <= length;146l.add(new Object[]{fromIndex, toIndex, length, withinBounds});147}148}149}150return l.toArray(Object[][]::new);151}152153@Test(dataProvider = "checkFromToIndexProvider")154public void testCheckFromToIndex(int fromIndex, int toIndex, int length, boolean withinBounds) {155String expectedMessage = withinBounds156? null157: Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new).158apply("checkFromToIndex", List.of(fromIndex, toIndex, length)).getMessage();159160BiConsumer<Class<? extends RuntimeException>, IntSupplier> check = (ec, s) -> {161try {162int rIndex = s.getAsInt();163if (!withinBounds)164fail(String.format(165"Range [%d, %d) is out of bounds of [0, %d), but was reported to be withing bounds", fromIndex, toIndex, length));166assertEquals(rIndex, fromIndex);167}168catch (RuntimeException e) {169assertTrue(ec.isInstance(e));170if (withinBounds)171fail(String.format(172"Range [%d, %d) is within bounds of [0, %d), but was reported to be out of bounds", fromIndex, toIndex, length));173else174assertEquals(e.getMessage(), expectedMessage);175}176};177178check.accept(AssertingOutOfBoundsException.class,179() -> Preconditions.checkFromToIndex(fromIndex, toIndex, length,180assertingOutOfBounds(expectedMessage, "checkFromToIndex", fromIndex, toIndex, length)));181check.accept(IndexOutOfBoundsException.class,182() -> Preconditions.checkFromToIndex(fromIndex, toIndex, length,183assertingOutOfBoundsReturnNull("checkFromToIndex", fromIndex, toIndex, length)));184check.accept(IndexOutOfBoundsException.class,185() -> Preconditions.checkFromToIndex(fromIndex, toIndex, length, null));186check.accept(IndexOutOfBoundsException.class,187() -> Objects.checkFromToIndex(fromIndex, toIndex, length));188check.accept(ArrayIndexOutOfBoundsException.class,189() -> Preconditions.checkFromToIndex(fromIndex, toIndex, length,190Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new)));191check.accept(StringIndexOutOfBoundsException.class,192() -> Preconditions.checkFromToIndex(fromIndex, toIndex, length,193Preconditions.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new)));194}195196197@DataProvider198static Object[][] checkFromIndexSizeProvider() {199List<Object[]> l = new ArrayList<>();200for (int fromIndex : VALUES) {201for (int size : VALUES) {202for (int length : VALUES) {203// Explicitly convert to long204long lFromIndex = fromIndex;205long lSize = size;206long lLength = length;207// Avoid overflow208long lToIndex = lFromIndex + lSize;209210boolean withinBounds = lFromIndex >= 0L &&211lSize >= 0L &&212lLength >= 0L &&213lFromIndex <= lToIndex &&214lToIndex <= lLength;215l.add(new Object[]{fromIndex, size, length, withinBounds});216}217}218}219return l.toArray(Object[][]::new);220}221222@Test(dataProvider = "checkFromIndexSizeProvider")223public void testCheckFromIndexSize(int fromIndex, int size, int length, boolean withinBounds) {224String expectedMessage = withinBounds225? null226: Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new).227apply("checkFromIndexSize", List.of(fromIndex, size, length)).getMessage();228229BiConsumer<Class<? extends RuntimeException>, IntSupplier> check = (ec, s) -> {230try {231int rIndex = s.getAsInt();232if (!withinBounds)233fail(String.format(234"Range [%d, %d + %d) is out of bounds of [0, %d), but was reported to be withing bounds", fromIndex, fromIndex, size, length));235assertEquals(rIndex, fromIndex);236}237catch (RuntimeException e) {238assertTrue(ec.isInstance(e));239if (withinBounds)240fail(String.format(241"Range [%d, %d + %d) is within bounds of [0, %d), but was reported to be out of bounds", fromIndex, fromIndex, size, length));242else243assertEquals(e.getMessage(), expectedMessage);244}245};246247check.accept(AssertingOutOfBoundsException.class,248() -> Preconditions.checkFromIndexSize(fromIndex, size, length,249assertingOutOfBounds(expectedMessage, "checkFromIndexSize", fromIndex, size, length)));250check.accept(IndexOutOfBoundsException.class,251() -> Preconditions.checkFromIndexSize(fromIndex, size, length,252assertingOutOfBoundsReturnNull("checkFromIndexSize", fromIndex, size, length)));253check.accept(IndexOutOfBoundsException.class,254() -> Preconditions.checkFromIndexSize(fromIndex, size, length, null));255check.accept(IndexOutOfBoundsException.class,256() -> Objects.checkFromIndexSize(fromIndex, size, length));257check.accept(ArrayIndexOutOfBoundsException.class,258() -> Preconditions.checkFromIndexSize(fromIndex, size, length,259Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new)));260check.accept(StringIndexOutOfBoundsException.class,261() -> Preconditions.checkFromIndexSize(fromIndex, size, length,262Preconditions.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new)));263}264265@Test266public void uniqueMessagesForCheckKinds() {267BiFunction<String, List<Number>, IndexOutOfBoundsException> f =268Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new);269270List<String> messages = new ArrayList<>();271// Exact arguments272messages.add(f.apply("checkIndex", List.of(-1, 0)).getMessage());273messages.add(f.apply("checkFromToIndex", List.of(-1, 0, 0)).getMessage());274messages.add(f.apply("checkFromIndexSize", List.of(-1, 0, 0)).getMessage());275// Unknown check kind276messages.add(f.apply("checkUnknown", List.of(-1, 0, 0)).getMessage());277// Known check kind with more arguments278messages.add(f.apply("checkIndex", List.of(-1, 0, 0)).getMessage());279messages.add(f.apply("checkFromToIndex", List.of(-1, 0, 0, 0)).getMessage());280messages.add(f.apply("checkFromIndexSize", List.of(-1, 0, 0, 0)).getMessage());281// Known check kind with fewer arguments282messages.add(f.apply("checkIndex", List.of(-1)).getMessage());283messages.add(f.apply("checkFromToIndex", List.of(-1, 0)).getMessage());284messages.add(f.apply("checkFromIndexSize", List.of(-1, 0)).getMessage());285// Null arguments286messages.add(f.apply(null, null).getMessage());287messages.add(f.apply("checkNullArguments", null).getMessage());288messages.add(f.apply(null, List.of(-1)).getMessage());289290assertEquals(messages.size(), messages.stream().distinct().count());291}292}293294295