/* * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/* * @test * @bug 8033148 8141409 * @summary tests for array equals and compare * @run testng ArraysEqCmpTest
*/
staticclass BoxedIntegers extends ArrayType<Integer[]> { public BoxedIntegers() { super(Integer[].class);
}
@Override void set(Object a, int i, Object v) { // Ensure unique reference
((Integer[]) a)[i] = v != null ? new Integer((Integer) v) : null;
}
}
staticclass BoxedIntegersWithReverseComparator extends BoxedIntegers { final Comparator<Integer> c = (a, b) -> { // Nulls sort after non-nulls if (a == null || b == null) return a == null ? b == null ? 0 : 1 : -1;
return Integer.compare(b, a);
};
final MethodHandle eqc; final MethodHandle eqcr; final MethodHandle cmpc; final MethodHandle cmpcr; final MethodHandle mismatchc; final MethodHandle mismatchcr;
public BoxedIntegersWithReverseComparator() { try {
MethodHandles.Lookup l = MethodHandles.lookup();
@Override void set(Object a, int i, Object v) { short pv; if (v instanceofShort) {
pv = (Short) v;
} elseif (v instanceof Integer) {
pv = ((Integer) v).shortValue();
} elsethrownew IllegalStateException();
@Override void set(Object a, int i, Object v) { int pv; if (v instanceof Integer) {
pv = ((Integer) v).shortValue();
} elsethrownew IllegalStateException();
@Override void set(Object a, int i, Object v) { long pv; if (v instanceofLong) {
pv = (Long) v;
} elseif (v instanceof Integer) {
pv = ((Integer) v).longValue();
} elsethrownew IllegalStateException();
((long[]) a)[i] = pv;
}
}
staticclass Floats extends ArrayType<float[]> { public Floats() { super(float[].class);
}
@Override void set(Object a, int i, Object v) { float pv; if (v instanceofFloat) {
pv = (Float) v;
} elseif (v instanceof Integer) {
pv = ((Integer) v).floatValue();
} elsethrownew IllegalStateException();
((float[]) a)[i] = pv;
}
}
staticclass Doubles extends ArrayType<double[]> { public Doubles() { super(double[].class);
}
@Override void set(Object a, int i, Object v) { double pv; if (v instanceofDouble) {
pv = (Double) v;
} elseif (v instanceof Integer) {
pv = ((Integer) v).doubleValue();
} elsethrownew IllegalStateException();
((double[]) a)[i] = pv;
}
}
}
static Object[][] arrayTypes;
@DataProvider publicstatic Object[][] arrayTypesProvider() { if (arrayTypes == null) {
arrayTypes = new Object[][]{ new Object[]{new ArrayType.BoxedIntegers()}, new Object[]{new ArrayType.BoxedIntegersWithReverseComparator()}, new Object[]{new ArrayType.Booleans()}, new Object[]{new ArrayType.Bytes(false)}, new Object[]{new ArrayType.Bytes(true)}, new Object[]{new ArrayType.Characters()}, new Object[]{new ArrayType.Shorts(false)}, new Object[]{new ArrayType.Shorts(true)}, new Object[]{new ArrayType.Integers(false)}, new Object[]{new ArrayType.Integers(true)}, new Object[]{new ArrayType.Longs(false)}, new Object[]{new ArrayType.Longs(true)}, new Object[]{new ArrayType.Floats()}, new Object[]{new ArrayType.Doubles()},
};
} return arrayTypes;
}
objectArrayTypes = new Object[][]{ new Object[]{new ArrayType.BoxedIntegers()}, new Object[]{new ArrayType.BoxedIntegersWithReverseComparator()},
};
} return objectArrayTypes;
}
static Object[][] signedUnsignedArrayTypes;
@DataProvider publicstatic Object[][] signedUnsignedArrayTypes() { if (signedUnsignedArrayTypes == null) {
signedUnsignedArrayTypes = new Object[][]{ new Object[]{new ArrayType.Bytes(false), new ArrayType.Bytes(true)}, new Object[]{new ArrayType.Shorts(false), new ArrayType.Shorts(true)}, new Object[]{new ArrayType.Integers(false), new ArrayType.Integers(true)}, new Object[]{new ArrayType.Longs(false), new ArrayType.Longs(true)},
};
} return signedUnsignedArrayTypes;
}
// Equality and comparison tests
@Test(dataProvider = "arrayTypesProvider") publicvoid testArray(ArrayType<?> arrayType) {
BiFunction<ArrayType<?>, Integer, Object> constructor = (at, s) -> {
Object a = at.construct(s); for (int x = 0; x < s; x++) {
at.set(a, x, x % 8);
} return a;
};
BiFunction<ArrayType<?>, Object, Object> cloner = (at, a) ->
constructor.apply(at, Array.getLength(a));
testArrayType(arrayType, constructor, cloner);
}
@Test(dataProvider = "floatArrayTypesProvider") publicvoid testPrimitiveFloatArray(
ArrayType<?> arrayType, long canonicalNanRawBits, long nonCanonicalNanRawBits,
LongFunction<Object> bitsToFloat) {
Object canonicalNan = bitsToFloat.apply(canonicalNanRawBits); // If conversion is a signalling NaN it may be subject to conversion to a // quiet NaN on some processors, even if a copy is performed // The tests assume that if conversion occurs it does not convert to the // canonical NaN
Object nonCanonicalNan = bitsToFloat.apply(nonCanonicalNanRawBits);
BiFunction<ArrayType<?>, Integer, Object> canonicalNaNs = (at, s) -> {
Object a = at.construct(s); for (int x = 0; x < s; x++) {
at.set(a, x, canonicalNan);
} return a;
};
BiFunction<ArrayType<?>, Object, Object> nonCanonicalNaNs = (at, a) -> { int s = Array.getLength(a);
Object ac = at.construct(s); for (int x = 0; x < s; x++) {
at.set(ac, x, nonCanonicalNan);
} return ac;
};
BiFunction<ArrayType<?>, Object, Object> halfNonCanonicalNaNs = (at, a) -> { int s = Array.getLength(a);
Object ac = at.construct(s); for (int x = 0; x < s / 2; x++) {
at.set(ac, x, nonCanonicalNan);
} for (int x = s / 2; x < s; x++) {
at.set(ac, x, 1);
} return ac;
};
// All nulls
testArrayType(arrayType,
(at, s) -> {
Object a = at.construct(s); for (int x = 0; x < s; x++) {
at.set(a, x, null);
} return a;
},
cloner);
// Some nulls
testArrayType(arrayType,
(at, s) -> {
Object a = at.construct(s); for (int x = 0; x < s; x++) { int v = x % 8;
at.set(a, x, v == 0 ? null : v);
} return a;
},
cloner);
Integer[] a = new Integer[]{null, 0};
Integer[] b = new Integer[]{0, 0}; Assert.assertTrue(Arrays.compare(a, b) < 0); Assert.assertTrue(Arrays.compare(b, a) > 0);
}
// One ref
Integer one = 1;
testArrayType(arrayType,
(at, s) -> {
Integer[] a = (Integer[]) at.construct(s); for (int x = 0; x < s; x++) {
a[x] = one;
} return a;
},
cloner);
// All ref
testArrayType(arrayType,
(at, s) -> {
Integer[] a = (Integer[]) at.construct(s); for (int x = 0; x < s; x++) {
a[x] = Integer.valueOf(s);
} return a;
},
cloner);
// Some same ref
testArrayType(arrayType,
(at, s) -> {
Integer[] a = (Integer[]) at.construct(s); for (int x = 0; x < s; x++) { int v = x % 8;
a[x] = v == 1 ? one : new Integer(v);
} return a;
},
cloner);
}
@Test(dataProvider = "signedUnsignedArrayTypes") publicvoid testSignedUnsignedArray(ArrayType<?> sat, ArrayType<?> uat) {
BiFunction<ArrayType<?>, Integer, Object> constructor = (at, s) -> {
Object a = at.construct(s); for (int x = 0; x < s; x++) {
at.set(a, x, 1);
} return a;
};
int n = arraySizeFor(sat.componentType);
for (int s : ranges(0, n)) {
Object a = constructor.apply(sat, s);
for (int aFrom : ranges(0, s)) { for (int aTo : ranges(aFrom, s)) { int aLength = aTo - aFrom;
if (aLength > 0) { for (int i = aFrom; i < aTo; i++) {
Object ac = sat.copyOf(a); // Create common prefix with a length of i - aFrom
sat.set(ac, i, -1);
int sc = sat.compare(ac, aFrom, aTo, a, aFrom, aTo); int uc = uat.compare(ac, aFrom, aTo, a, aFrom, aTo);
Assert.assertEquals(at.mismatch(a, aFrom, aTo, b, bFrom, bTo), -1); Assert.assertEquals(at.mismatch(b, bFrom, bTo, a, aFrom, aTo), -1); Assert.assertEquals(at.mismatch(anr, bnr), -1); Assert.assertEquals(at.mismatch(bnr, anr), -1);
} else { int aCb = at.compare(a, aFrom, aTo, b, bFrom, bTo); int bCa = at.compare(b, bFrom, bTo, a, aFrom, aTo); int v = Integer.signum(aCb) * Integer.signum(bCa); Assert.assertTrue(v == -1);
int anrCbnr = at.compare(anr, bnr); int bnrCanr = at.compare(bnr, anr); Assert.assertEquals(anrCbnr, aCb); Assert.assertEquals(bnrCanr, bCa);
int aMb = at.mismatch(a, aFrom, aTo, b, bFrom, bTo); int bMa = at.mismatch(b, bFrom, bTo, a, aFrom, aTo); int anrMbnr = at.mismatch(anr, bnr); int bnrManr = at.mismatch(bnr, anr);
Assert.assertFalse(at.equals(ac, aFrom, aTo, a, aFrom, aTo)); Assert.assertFalse(at.equals(acnr, anr));
int acCa = at.compare(ac, aFrom, aTo, a, aFrom, aTo); int aCac = at.compare(a, aFrom, aTo, ac, aFrom, aTo); int v = Integer.signum(acCa) * Integer.signum(aCac); Assert.assertTrue(v == -1);
int acnrCanr = at.compare(acnr, anr); int anrCacnr = at.compare(anr, acnr); Assert.assertEquals(acnrCanr, acCa); Assert.assertEquals(anrCacnr, aCac);
int acMa = at.mismatch(ac, aFrom, aTo, a, aFrom, aTo); int aMac = at.mismatch(a, aFrom, aTo, ac, aFrom, aTo); Assert.assertEquals(acMa, aMac); Assert.assertEquals(acMa, i - aFrom);
int acnrManr = at.mismatch(acnr, anr); int anrMacnr = at.mismatch(anr, acnr); Assert.assertEquals(acnrManr, anrMacnr); Assert.assertEquals(acnrManr, i - aFrom);
}
}
}
}
}
}
staticboolean isEqual(ArrayType<?> at, Object a, int aFromIndex, int aToIndex,
Object b, int bFromIndex, int bToIndex) { int aLength = aToIndex - aFromIndex; int bLength = bToIndex - bFromIndex; if (aLength != bLength) returnfalse;
for (int i = 0; i < aLength; i++) {
Object av = at.get(a, aFromIndex++);
Object bv = at.get(b, bFromIndex++); if (!Objects.equals(av, bv)) returnfalse;
}
returntrue;
}
staticboolean isEqual(ArrayType<?> at, Object a, int aFrom, Object b, int bFrom) {
Object av = at.get(a, aFrom);
Object bv = at.get(b, bFrom);
return Objects.equals(av, bv);
}
staticint[] ranges(int from, int to) { int width = to - from; switch (width) { case 0: returnnewint[]{}; case 1: returnnewint[]{from, to}; case 2: returnnewint[]{from, from + 1, to}; case 3: returnnewint[]{from, from + 1, from + 2, to}; default: return IntStream.of(from, from + 1, from + 2, to / 2 - 1, to / 2, to / 2 + 1, to - 2, to - 1, to)
.filter(i -> i >= from && i <= to)
.distinct().toArray();
}
}
// Null array reference tests
@Test(dataProvider = "arrayTypesProvider") publicvoid testNullArrayRefs(ArrayType<?> arrayType) {
Object n = null;
Object a = arrayType.construct(0);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.