/* * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.facebook.jni; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.offset; import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; import org.junit.Ignore; import org.junit.Test; public class PrimitiveArrayTests extends BaseFBJniTests { private static final int MAGIC = 42; @Test public void testMakeArrays() { assertThat(nativeTestMakeBooleanArray(MAGIC).length).isEqualTo(MAGIC); assertThat(nativeTestMakeByteArray(MAGIC).length).isEqualTo(MAGIC); assertThat(nativeTestMakeCharArray(MAGIC).length).isEqualTo(MAGIC); assertThat(nativeTestMakeShortArray(MAGIC).length).isEqualTo(MAGIC); assertThat(nativeTestMakeIntArray(MAGIC).length).isEqualTo(MAGIC); assertThat(nativeTestMakeLongArray(MAGIC).length).isEqualTo(MAGIC); assertThat(nativeTestMakeFloatArray(MAGIC).length).isEqualTo(MAGIC); assertThat(nativeTestMakeDoubleArray(MAGIC).length).isEqualTo(MAGIC); } private static native boolean[] nativeTestMakeBooleanArray(int size); private static native byte[] nativeTestMakeByteArray(int size); private static native char[] nativeTestMakeCharArray(int size); private static native short[] nativeTestMakeShortArray(int size); private static native int[] nativeTestMakeIntArray(int size); private static native long[] nativeTestMakeLongArray(int size); private static native float[] nativeTestMakeFloatArray(int size); private static native double[] nativeTestMakeDoubleArray(int size); @Test public void testGetSetBooleanArray() { boolean[] array = {false, true}; assertThat(nativeTestGetSetBooleanArray(array)).isTrue(); assertThat(array).isEqualTo(new boolean[] {true, false}); } private static native boolean nativeTestGetSetBooleanArray(boolean[] array); @Test public void testPinBooleanArray() { boolean[] array = {false, true}; assertThat(nativeTestPinBooleanArray(array)).isTrue(); assertThat(array).isEqualTo(new boolean[] {true, false}); } private static native boolean nativeTestPinBooleanArray(boolean[] array); @Test public void testGetSetByteArray() { byte[] array = new byte[MAGIC]; for (int i = 0; i < array.length; ++i) { array[i] = (byte) i; } assertThat(nativeTestGetSetByteArray(array)).isTrue(); for (int i = 0; i < array.length; ++i) { assertThat(array[i]).isEqualTo((byte) (2 * i)); } } private static native boolean nativeTestGetSetByteArray(byte[] array); @Test public void testGetSetCharArray() { char[] array = new char[MAGIC]; for (int i = 0; i < array.length; ++i) { array[i] = (char) i; } assertThat(nativeTestGetSetCharArray(array)).isTrue(); for (int i = 0; i < array.length; ++i) { assertThat(array[i]).isEqualTo((char) (2 * i)); } } private static native boolean nativeTestGetSetCharArray(char[] array); @Test public void testGetSetShortArray() { short[] array = new short[MAGIC]; for (int i = 0; i < array.length; ++i) { array[i] = (short) i; } assertThat(nativeTestGetSetShortArray(array)).isTrue(); for (int i = 0; i < array.length; ++i) { assertThat(array[i]).isEqualTo((short) (2 * i)); } } private static native boolean nativeTestGetSetShortArray(short[] array); @Test public void testGetSetIntArray() { int[] intArray = new int[MAGIC]; for (int i = 0; i < intArray.length; ++i) { intArray[i] = i; } assertThat(nativeTestGetSetIntArray(intArray)).isTrue(); for (int i = 0; i < intArray.length; ++i) { assertThat(intArray[i]).isEqualTo(2 * i); } } private static native boolean nativeTestGetSetIntArray(int[] array); @Test public void testGetSetLongArray() { long[] longArray = new long[MAGIC]; for (int i = 0; i < longArray.length; ++i) { longArray[i] = (long) i; } assertThat(nativeTestGetSetLongArray(longArray)).isTrue(); for (int i = 0; i < longArray.length; ++i) { assertThat(longArray[i]).isEqualTo(2 * i); } } private static native boolean nativeTestGetSetLongArray(long[] array); @Test public void testGetSetFloatArray() { float[] floatArray = new float[MAGIC]; for (int i = 0; i < floatArray.length; ++i) { floatArray[i] = i; } assertThat(nativeTestGetSetFloatArray(floatArray)).isTrue(); for (int i = 0; i < floatArray.length; ++i) { assertThat(floatArray[i]).isEqualTo(2 * i, offset(1e-3f)); } } private static native boolean nativeTestGetSetFloatArray(float[] array); @Test public void testGetSetDoubleArray() { double[] doubleArray = new double[MAGIC]; for (int i = 0; i < doubleArray.length; ++i) { doubleArray[i] = i; } assertThat(nativeTestGetSetDoubleArray(doubleArray)).isTrue(); for (int i = 0; i < doubleArray.length; ++i) { assertThat(doubleArray[i]).isEqualTo(2 * i, offset(1e-3)); } } private static native boolean nativeTestGetSetDoubleArray(double[] array); @Test public void testPinByteArray() { byte[] array = new byte[MAGIC]; for (int i = 0; i < array.length; ++i) { array[i] = (byte) i; } assertThat(nativeTestPinByteArray(array)).isTrue(); for (int i = 0; i < array.length; ++i) { assertThat(array[i]).isEqualTo((byte) (2 * i)); } } private static native boolean nativeTestPinByteArray(byte[] array); @Test public void testPinCharArray() { char[] array = new char[MAGIC]; for (int i = 0; i < array.length; ++i) { array[i] = (char) i; } assertThat(nativeTestPinCharArray(array)).isTrue(); for (int i = 0; i < array.length; ++i) { assertThat(array[i]).isEqualTo((char) (2 * i)); } } private static native boolean nativeTestPinCharArray(char[] array); @Test public void testPinShortArray() { short[] array = new short[MAGIC]; for (int i = 0; i < array.length; ++i) { array[i] = (short) i; } assertThat(nativeTestPinShortArray(array)).isTrue(); for (int i = 0; i < array.length; ++i) { assertThat(array[i]).isEqualTo((short) (2 * i)); } } private static native boolean nativeTestPinShortArray(short[] array); @Test public void testPinIntArray() { int[] intArray = new int[MAGIC]; for (int i = 0; i < intArray.length; ++i) { intArray[i] = i; } assertThat(nativeTestPinIntArray(intArray)).isTrue(); for (int i = 0; i < intArray.length; ++i) { assertThat(intArray[i]).isEqualTo(2 * i); } } private static native boolean nativeTestPinIntArray(int[] array); @Test public void testPinLongArray() { long[] longArray = new long[MAGIC]; for (int i = 0; i < longArray.length; ++i) { longArray[i] = (long) i; } assertThat(nativeTestPinLongArray(longArray)).isTrue(); for (int i = 0; i < longArray.length; ++i) { assertThat(longArray[i]).isEqualTo(2 * i); } } private static native boolean nativeTestPinLongArray(long[] array); @Test public void testPinFloatArray() { float[] floatArray = new float[MAGIC]; for (int i = 0; i < floatArray.length; ++i) { floatArray[i] = (long) i; } assertThat(nativeTestPinFloatArray(floatArray)).isTrue(); for (int i = 0; i < floatArray.length; ++i) { assertThat(floatArray[i]).isEqualTo(2 * i, offset(1e-3f)); } } private static native boolean nativeTestPinFloatArray(float[] array); @Test public void testPinDoubleArray() { double[] doubleArray = new double[MAGIC]; for (int i = 0; i < doubleArray.length; ++i) { doubleArray[i] = (double) i; } assertThat(nativeTestPinDoubleArray(doubleArray)).isTrue(); for (int i = 0; i < doubleArray.length; ++i) { assertThat(doubleArray[i]).isEqualTo(2 * i, offset(1e-3)); } } private static native boolean nativeTestPinDoubleArray(double[] array); @Test public void testPinByteArrayRegion() { byte[] array = new byte[MAGIC]; for (int i = 0; i < array.length; ++i) { array[i] = (byte) i; } assertThat(nativeTestPinByteArrayRegion(array)).isTrue(); for (int i = 0; i < array.length; ++i) { assertThat(array[i]).isEqualTo((byte) (2 * i)); } } private static native boolean nativeTestPinByteArrayRegion(byte[] array); @Test public void testPinCharArrayRegion() { char[] array = new char[MAGIC]; for (int i = 0; i < array.length; ++i) { array[i] = (char) i; } assertThat(nativeTestPinCharArrayRegion(array)).isTrue(); for (int i = 0; i < array.length; ++i) { assertThat(array[i]).isEqualTo((char) (2 * i)); } } private static native boolean nativeTestPinCharArrayRegion(char[] array); @Test public void testPinShortArrayRegion() { short[] array = new short[MAGIC]; for (int i = 0; i < array.length; ++i) { array[i] = (short) i; } assertThat(nativeTestPinShortArrayRegion(array)).isTrue(); for (int i = 0; i < array.length; ++i) { assertThat(array[i]).isEqualTo((short) (2 * i)); } } private static native boolean nativeTestPinShortArrayRegion(short[] array); @Test public void testPinIntArrayRegion() { int[] intArray = new int[MAGIC]; for (int i = 0; i < intArray.length; ++i) { intArray[i] = i; } assertThat(nativeTestPinIntArrayRegion(intArray)).isTrue(); for (int i = 0; i < intArray.length; ++i) { assertThat(intArray[i]).isEqualTo(2 * i); } } private static native boolean nativeTestPinIntArrayRegion(int[] array); @Test public void testPinLongArrayRegion() { long[] longArray = new long[MAGIC]; for (int i = 0; i < longArray.length; ++i) { longArray[i] = (long) i; } assertThat(nativeTestPinLongArrayRegion(longArray)).isTrue(); for (int i = 0; i < longArray.length; ++i) { assertThat(longArray[i]).isEqualTo(2 * i); } } private static native boolean nativeTestPinLongArrayRegion(long[] array); @Test public void testPinFloatArrayRegion() { float[] floatArray = new float[MAGIC]; for (int i = 0; i < floatArray.length; ++i) { floatArray[i] = (long) i; } assertThat(nativeTestPinFloatArrayRegion(floatArray)).isTrue(); for (int i = 0; i < floatArray.length; ++i) { assertThat(floatArray[i]).isEqualTo(2 * i, offset(1e-3f)); } } private static native boolean nativeTestPinFloatArrayRegion(float[] array); @Test public void testPinDoubleArrayRegion() { double[] doubleArray = new double[MAGIC]; for (int i = 0; i < doubleArray.length; ++i) { doubleArray[i] = (double) i; } assertThat(nativeTestPinDoubleArrayRegion(doubleArray)).isTrue(); for (int i = 0; i < doubleArray.length; ++i) { assertThat(doubleArray[i]).isEqualTo(2 * i, offset(1e-3)); } } private static native boolean nativeTestPinDoubleArrayRegion(double[] array); @Test public void testPinByteArrayCritical() { byte[] array = new byte[MAGIC]; for (int i = 0; i < array.length; ++i) { array[i] = (byte) i; } assertThat(nativeTestPinByteArrayCritical(array)).isTrue(); for (int i = 0; i < array.length; ++i) { assertThat(array[i]).isEqualTo((byte) (2 * i)); } } private static native boolean nativeTestPinByteArrayCritical(byte[] array); @Test public void testPinCharArrayCritical() { char[] array = new char[MAGIC]; for (int i = 0; i < array.length; ++i) { array[i] = (char) i; } assertThat(nativeTestPinCharArrayCritical(array)).isTrue(); for (int i = 0; i < array.length; ++i) { assertThat(array[i]).isEqualTo((char) (2 * i)); } } private static native boolean nativeTestPinCharArrayCritical(char[] array); @Test public void testPinShortArrayCritical() { short[] array = new short[MAGIC]; for (int i = 0; i < array.length; ++i) { array[i] = (short) i; } assertThat(nativeTestPinShortArrayCritical(array)).isTrue(); for (int i = 0; i < array.length; ++i) { assertThat(array[i]).isEqualTo((short) (2 * i)); } } private static native boolean nativeTestPinShortArrayCritical(short[] array); @Test public void testPinIntArrayCritical() { int[] intArray = new int[MAGIC]; for (int i = 0; i < intArray.length; ++i) { intArray[i] = i; } assertThat(nativeTestPinIntArrayCritical(intArray)).isTrue(); for (int i = 0; i < intArray.length; ++i) { assertThat(intArray[i]).isEqualTo(2 * i); } } private static native boolean nativeTestPinIntArrayCritical(int[] array); @Test public void testPinLongArrayCritical() { long[] longArray = new long[MAGIC]; for (int i = 0; i < longArray.length; ++i) { longArray[i] = (long) i; } assertThat(nativeTestPinLongArrayCritical(longArray)).isTrue(); for (int i = 0; i < longArray.length; ++i) { assertThat(longArray[i]).isEqualTo(2 * i); } } private static native boolean nativeTestPinLongArrayCritical(long[] array); @Test public void testPinFloatArrayCritical() { float[] floatArray = new float[MAGIC]; for (int i = 0; i < floatArray.length; ++i) { floatArray[i] = (long) i; } assertThat(nativeTestPinFloatArrayCritical(floatArray)).isTrue(); for (int i = 0; i < floatArray.length; ++i) { assertThat(floatArray[i]).isEqualTo(2 * i, offset(1e-3f)); } } private static native boolean nativeTestPinFloatArrayCritical(float[] array); @Test public void testPinDoubleArrayCritical() { double[] doubleArray = new double[MAGIC]; for (int i = 0; i < doubleArray.length; ++i) { doubleArray[i] = (double) i; } assertThat(nativeTestPinDoubleArrayCritical(doubleArray)).isTrue(); for (int i = 0; i < doubleArray.length; ++i) { assertThat(doubleArray[i]).isEqualTo(2 * i, offset(1e-3)); } } private static native boolean nativeTestPinDoubleArrayCritical(double[] array); @Test public void testIndexOutOfBoundsInRegions() { assertThat(nativeTestIndexOutOfBoundsInRegions()).isTrue(); } private static native boolean nativeTestIndexOutOfBoundsInRegions(); @Test public void testBooleanArrayIndexing() { boolean[] array = {true, true, false, true, false}; for (int ii = 0; ii < 5; ii++) { assertThat(nativeTestBooleanArrayIndexing(array, ii)).isEqualTo(array[ii]); } } private native boolean nativeTestBooleanArrayIndexing(boolean[] array, int idx); @Test public void testIntegerArrayIndexing() { int[] array = {0, 1, 2, 3, 4}; for (int ii = 0; ii < 5; ii++) { assertThat(nativeTestIntegerArrayIndexing(array, ii)).isEqualTo(array[ii]); } } private native int nativeTestIntegerArrayIndexing(int[] array, int idx); @Test public void testIntegerArraySize() { int[] array = {0, 1, 2, 3, 4}; assertThat(nativeTestIntegerArraySize(array)).isEqualTo(array.length); } private native int nativeTestIntegerArraySize(int[] array); @Test public void testIntegerArrayIncrement() { int[] array = {0, 1, 2, 3, 4}; array = nativeTestIntegerArrayIncrement(array); for (int ii = 0; ii < 5; ii++) { assertThat(array[ii]).isEqualTo(ii + 1); } } private native int[] nativeTestIntegerArrayIncrement(int[] array); @Test public void testIntegerArrayMoveAssignment() { int[] array = {0, 1, 2, 3, 4}; nativeTestIntegerArrayMoveAssignment(array); assertThat(array[0]).isEqualTo(0); } private native void nativeTestIntegerArrayMoveAssignment(int[] array); // On ART, a large array will be placed in the large heap. Arrays here are // non-movable and so the vm pins them in-place. A small array will be a // movable object and thus the pinned array will be a copy. // On Dalvik, all pinned arrays are in-place. @Test @Ignore("Flakey Test. See t8845133") public void testCopiedPinnedArray() { int[] array = new int[100]; assumeTrue(nativeIsPinnedArrayACopy(array)); assertThat(nativeTestCopiedPinnedArray(array)).isTrue(); } @Test public void testNonCopiedPinnedArray() { int[] array = new int[1000000]; assumeFalse(nativeIsPinnedArrayACopy(array)); assertThat(nativeTestNonCopiedPinnedArray(array)).isTrue(); } private native boolean nativeIsPinnedArrayACopy(int[] array); private native boolean nativeTestCopiedPinnedArray(int[] array); private native boolean nativeTestNonCopiedPinnedArray(int[] array); }