Merge "Revert "Rewrite scoped arrays with template and introduced nullable one.""
am: 9042585fa0
Change-Id: Ide0f0b5580ded28c962aa68b215abc9744d359fd
diff --git a/header_only_include/nativehelper/scoped_primitive_array.h b/header_only_include/nativehelper/scoped_primitive_array.h
index 17f18a3..d6840c2 100644
--- a/header_only_include/nativehelper/scoped_primitive_array.h
+++ b/header_only_include/nativehelper/scoped_primitive_array.h
@@ -17,10 +17,6 @@
#ifndef SCOPED_PRIMITIVE_ARRAY_H_
#define SCOPED_PRIMITIVE_ARRAY_H_
-#include <type_traits>
-
-#include <sys/types.h> // For ssize_t
-
#include "jni.h"
#include "nativehelper_utils.h"
@@ -30,184 +26,122 @@
#define POINTER_TYPE(T) T* /* NOLINT */
#endif
-template<typename JType> struct ScopedPrimitiveArrayTraits {};
+#ifdef REFERENCE_TYPE
+#error REFERENCE_TYPE is defined.
+#else
+#define REFERENCE_TYPE(T) T& /* NOLINT */
+#endif
-#define ARRAY_TRAITS(ARRAY_TYPE, JTYPE, NAME) \
-template<> struct ScopedPrimitiveArrayTraits<JTYPE> { \
-public: \
- static inline void getArrayRegion(JNIEnv* env, ARRAY_TYPE array, size_t start, \
- size_t len, POINTER_TYPE(JTYPE) out) { \
- env->Get ## NAME ## ArrayRegion(array, start, len, out); \
- } \
- \
- static inline POINTER_TYPE(JTYPE) getArrayElements(JNIEnv* env, ARRAY_TYPE array) { \
- return env->Get ## NAME ## ArrayElements(array, nullptr); \
- } \
- \
- static inline void releaseArrayElements(JNIEnv* env, ARRAY_TYPE array, \
- POINTER_TYPE(JTYPE) buffer, jint mode) { \
- env->Release ## NAME ## ArrayElements(array, buffer, mode); \
- } \
- static inline size_t getArrayLength(JNIEnv* env, ARRAY_TYPE array) { \
- return env->GetArrayLength(array); \
- } \
- static inline void fatalError(JNIEnv* env, const char*msg) { \
- env->FatalError(msg); \
- } \
- using ArrayType = ARRAY_TYPE; \
-}; \
+// ScopedBooleanArrayRO, ScopedByteArrayRO, ScopedCharArrayRO, ScopedDoubleArrayRO,
+// ScopedFloatArrayRO, ScopedIntArrayRO, ScopedLongArrayRO, and ScopedShortArrayRO provide
+// convenient read-only access to Java arrays from JNI code. This is cheaper than read-write
+// access and should be used by default.
+#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(PRIMITIVE_TYPE, NAME) \
+ class Scoped ## NAME ## ArrayRO { \
+ public: \
+ explicit Scoped ## NAME ## ArrayRO(JNIEnv* env) \
+ : mEnv(env), mJavaArray(NULL), mRawArray(NULL), mSize(0) {} \
+ Scoped ## NAME ## ArrayRO(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \
+ : mEnv(env) { \
+ if (javaArray == NULL) { \
+ mJavaArray = NULL; \
+ mSize = 0; \
+ mRawArray = NULL; \
+ jniThrowNullPointerException(mEnv, NULL); \
+ } else { \
+ reset(javaArray); \
+ } \
+ } \
+ ~Scoped ## NAME ## ArrayRO() { \
+ if (mRawArray != NULL && mRawArray != mBuffer) { \
+ mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, JNI_ABORT); \
+ } \
+ } \
+ void reset(PRIMITIVE_TYPE ## Array javaArray) { \
+ mJavaArray = javaArray; \
+ mSize = mEnv->GetArrayLength(mJavaArray); \
+ if (mSize <= buffer_size) { \
+ mEnv->Get ## NAME ## ArrayRegion(mJavaArray, 0, mSize, mBuffer); \
+ mRawArray = mBuffer; \
+ } else { \
+ mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
+ } \
+ } \
+ const PRIMITIVE_TYPE* get() const { return mRawArray; } \
+ PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \
+ const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \
+ size_t size() const { return mSize; } \
+ private: \
+ static const jsize buffer_size = 1024; \
+ JNIEnv* const mEnv; \
+ PRIMITIVE_TYPE ## Array mJavaArray; \
+ POINTER_TYPE(PRIMITIVE_TYPE) mRawArray; \
+ jsize mSize; \
+ PRIMITIVE_TYPE mBuffer[buffer_size]; \
+ DISALLOW_COPY_AND_ASSIGN(Scoped ## NAME ## ArrayRO); \
+ }
-ARRAY_TRAITS(jbooleanArray, jboolean, Boolean)
-ARRAY_TRAITS(jbyteArray, jbyte, Byte)
-ARRAY_TRAITS(jcharArray, jchar, Char)
-ARRAY_TRAITS(jdoubleArray, jdouble, Double)
-ARRAY_TRAITS(jfloatArray, jfloat, Float)
-ARRAY_TRAITS(jintArray, jint, Int)
-ARRAY_TRAITS(jlongArray, jlong, Long)
-ARRAY_TRAITS(jshortArray, jshort, Short)
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jboolean, Boolean);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jbyte, Byte);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jchar, Char);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jdouble, Double);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jfloat, Float);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jint, Int);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jlong, Long);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jshort, Short);
-#undef ARRAY_TRAITS
+#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO
+
+// ScopedBooleanArrayRW, ScopedByteArrayRW, ScopedCharArrayRW, ScopedDoubleArrayRW,
+// ScopedFloatArrayRW, ScopedIntArrayRW, ScopedLongArrayRW, and ScopedShortArrayRW provide
+// convenient read-write access to Java arrays from JNI code. These are more expensive,
+// since they entail a copy back onto the Java heap, and should only be used when necessary.
+#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(PRIMITIVE_TYPE, NAME) \
+ class Scoped ## NAME ## ArrayRW { \
+ public: \
+ explicit Scoped ## NAME ## ArrayRW(JNIEnv* env) \
+ : mEnv(env), mJavaArray(NULL), mRawArray(NULL) {} \
+ Scoped ## NAME ## ArrayRW(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \
+ : mEnv(env), mJavaArray(javaArray), mRawArray(NULL) { \
+ if (mJavaArray == NULL) { \
+ jniThrowNullPointerException(mEnv, NULL); \
+ } else { \
+ mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
+ } \
+ } \
+ ~Scoped ## NAME ## ArrayRW() { \
+ if (mRawArray) { \
+ mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, 0); \
+ } \
+ } \
+ void reset(PRIMITIVE_TYPE ## Array javaArray) { \
+ mJavaArray = javaArray; \
+ mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
+ } \
+ const PRIMITIVE_TYPE* get() const { return mRawArray; } \
+ PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \
+ const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \
+ POINTER_TYPE(PRIMITIVE_TYPE) get() { return mRawArray; } \
+ REFERENCE_TYPE(PRIMITIVE_TYPE) operator[](size_t n) { return mRawArray[n]; } \
+ size_t size() const { return mEnv->GetArrayLength(mJavaArray); } \
+ private: \
+ JNIEnv* const mEnv; \
+ PRIMITIVE_TYPE ## Array mJavaArray; \
+ POINTER_TYPE(PRIMITIVE_TYPE) mRawArray; \
+ DISALLOW_COPY_AND_ASSIGN(Scoped ## NAME ## ArrayRW); \
+ }
+
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jboolean, Boolean);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jbyte, Byte);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jchar, Char);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jdouble, Double);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jfloat, Float);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jint, Int);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jlong, Long);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jshort, Short);
+
+#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW
#undef POINTER_TYPE
-
-template<typename JType, bool kNullable>
-class ScopedArrayRO {
-public:
- using Traits = ScopedPrimitiveArrayTraits<JType>;
- using ArrayType = typename Traits::ArrayType;
- using const_iterator = const JType*;
-
- // Provides read-only access to Java array from JNI code.
- // env must not be nullptr.
- // If kNullable is false, this aborts if javaArray is nullptr.
- ScopedArrayRO(JNIEnv* env, ArrayType javaArray) : mEnv(env), mJavaArray(javaArray) {
- if (mJavaArray == nullptr) {
- mSize = -1;
- mRawArray = nullptr;
- if (!kNullable) {
- Traits::fatalError(mEnv, "javaArray is null");
- }
- } else {
- mSize = Traits::getArrayLength(mEnv, mJavaArray);
- if (mSize <= BUFFER_SIZE) {
- Traits::getArrayRegion(mEnv, mJavaArray, 0, mSize, mBuffer);
- mRawArray = mBuffer;
- } else {
- mRawArray = Traits::getArrayElements(mEnv, mJavaArray);
- }
- }
- }
-
- ~ScopedArrayRO() {
- if (mRawArray != nullptr && mRawArray != mBuffer) {
- Traits::releaseArrayElements(mEnv, mJavaArray, mRawArray, JNI_ABORT);
- }
- }
-
- const JType* get() const { return mRawArray; }
- ArrayType getJavaArray() const { return mJavaArray; }
- const JType& operator[](size_t n) const { return mRawArray[n]; }
- const_iterator begin() const { return get(); }
- const_iterator end() const {
- return (kNullable && mRawArray == nullptr) ? get() : get() + mSize;
- }
-
- using SizeT = typename std::conditional<kNullable, ssize_t, size_t>::type;
- // In case of nonnull array, the return type is size_t.
- // In case of nullable array, the return type is ssize_t. Then, will return -1 if this is
- // constructed with null array.
- SizeT size() const { return mSize; }
-
-private:
- // 1024 since there is stack frame size limitation (4096 bytes).
- constexpr static jsize BUFFER_SIZE = 1024 / sizeof(JType);
-
- JNIEnv* const mEnv;
- ArrayType mJavaArray;
- JType* mRawArray;
- SizeT mSize;
-
- // Speed-up JNI array access for small arrays, see I703d7346de732199be1feadbead021c6647a554a
- // for more details.
- JType mBuffer[BUFFER_SIZE];
-
- DISALLOW_COPY_AND_ASSIGN(ScopedArrayRO);
-};
-
-// Scoped***ArrayRO provide convenient read-only access to Java array from JNI code.
-// This is cheaper than read-write access and should be used by default.
-// These abort if nullptr is passed.
-using ScopedBooleanArrayRO = ScopedArrayRO<jboolean, false>;
-using ScopedByteArrayRO = ScopedArrayRO<jbyte, false>;
-using ScopedCharArrayRO = ScopedArrayRO<jchar, false>;
-using ScopedDoubleArrayRO = ScopedArrayRO<jdouble, false>;
-using ScopedFloatArrayRO = ScopedArrayRO<jfloat, false>;
-using ScopedIntArrayRO = ScopedArrayRO<jint, false>;
-using ScopedLongArrayRO = ScopedArrayRO<jlong, false>;
-using ScopedShortArrayRO = ScopedArrayRO<jshort, false>;
-
-// ScopedNullable***ArrayRO also provide convenient read-only access to Java array from JNI code.
-// These accept nullptr. In that case, get() returns nullptr and size() returns -1.
-using ScopedNullableBooleanArrayRO = ScopedArrayRO<jboolean, true>;
-using ScopedNullableByteArrayRO = ScopedArrayRO<jbyte, true>;
-using ScopedNullableCharArrayRO = ScopedArrayRO<jchar, true>;
-using ScopedNullableDoubleArrayRO = ScopedArrayRO<jdouble, true>;
-using ScopedNullableFloatArrayRO = ScopedArrayRO<jfloat, true>;
-using ScopedNullableIntArrayRO = ScopedArrayRO<jint, true>;
-using ScopedNullableLongArrayRO = ScopedArrayRO<jlong, true>;
-using ScopedNullableShortArrayRO = ScopedArrayRO<jshort, true>;
-
-template<typename JType>
-class ScopedArrayRW {
-public:
- using Traits = ScopedPrimitiveArrayTraits<JType>;
- using ArrayType = typename Traits::ArrayType;
- using const_iterator = const JType*;
- using iterator = JType*;
-
- ScopedArrayRW(JNIEnv* env, ArrayType javaArray) : mEnv(env), mJavaArray(javaArray) {
- if (mJavaArray == nullptr) {
- Traits::fatalError(mEnv, "javaArray is null");
- } else {
- mSize = Traits::getArrayLength(mEnv, mJavaArray);
- mRawArray = Traits::getArrayElements(mEnv, mJavaArray);
- }
- }
- ~ScopedArrayRW() {
- if (mRawArray != nullptr) {
- Traits::releaseArrayElements(mEnv, mJavaArray, mRawArray, 0);
- }
- }
-
- const JType* get() const { return mRawArray; }
- ArrayType getJavaArray() const { return mJavaArray; }
- const JType& operator[](size_t n) const { return mRawArray[n]; }
- const_iterator cbegin() const { return get(); }
- const_iterator cend() const { return get() + mSize; }
- JType* get() { return mRawArray; }
- JType& operator[](size_t n) { return mRawArray[n]; }
- iterator begin() { return get(); }
- iterator end() { return get() + mSize; }
- size_t size() const { return mSize; }
-
-private:
- JNIEnv* const mEnv;
- ArrayType mJavaArray;
- JType* mRawArray;
- jsize mSize;
- DISALLOW_COPY_AND_ASSIGN(ScopedArrayRW);
-};
-
-// Scoped***ArrayRW provide convenient read-write access to Java arrays from JNI code.
-// These are more expensive, since they entail a copy back onto the Java heap, and should only be
-// used when necessary.
-// These abort if nullptr is passed.
-using ScopedBooleanArrayRW = ScopedArrayRW<jboolean>;
-using ScopedByteArrayRW = ScopedArrayRW<jbyte>;
-using ScopedCharArrayRW = ScopedArrayRW<jchar>;
-using ScopedDoubleArrayRW = ScopedArrayRW<jdouble>;
-using ScopedFloatArrayRW = ScopedArrayRW<jfloat>;
-using ScopedIntArrayRW = ScopedArrayRW<jint>;
-using ScopedLongArrayRW = ScopedArrayRW<jlong>;
-using ScopedShortArrayRW = ScopedArrayRW<jshort>;
+#undef REFERENCE_TYPE
#endif // SCOPED_PRIMITIVE_ARRAY_H_
diff --git a/tests/Android.bp b/tests/Android.bp
index d30b4d2..e6cbf5c 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -4,10 +4,7 @@
name: "JniInvocation_test",
test_suites: ["device-tests"],
host_supported: true,
- srcs: [
- "JniInvocation_test.cpp",
- "scoped_primitive_array_test.cpp"
- ],
+ srcs: ["JniInvocation_test.cpp"],
cflags: ["-Wall", "-Werror"],
shared_libs: ["libnativehelper"],
}
diff --git a/tests/scoped_primitive_array_test.cpp b/tests/scoped_primitive_array_test.cpp
deleted file mode 100644
index cba258c..0000000
--- a/tests/scoped_primitive_array_test.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * 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.
- */
-
-#include <nativehelper/scoped_primitive_array.h>
-
-#include <gtest/gtest.h>
-
-struct TestType { char dummy[1]; };
-using jTestTypeArray = void*;
-
-const jTestTypeArray LARGE_ARRAY = reinterpret_cast<jTestTypeArray>(0x1);
-const jTestTypeArray SMALL_ARRAY = reinterpret_cast<jTestTypeArray>(0x2);
-
-constexpr size_t LARGE_ARRAY_SIZE = 8192;
-constexpr size_t SMALL_ARRAY_SIZE = 32;
-
-struct TestContext {
- TestType* dummyPtr;
-
- int getArrayElementsCallCount = 0;
- int releaseArrayElementsCallCount = 0;
- bool aborted = false;
- bool elementsUpdated = false;
-
- void resetCallCount() {
- getArrayElementsCallCount = 0;
- releaseArrayElementsCallCount = 0;
- aborted = false;
- elementsUpdated = false;
- }
-
- bool memoryUpdated() const {
- return releaseArrayElementsCallCount > 0 && elementsUpdated;
- }
-};
-
-// Mock implementation of the ScopedPrimitiveArrayTraits.
-// JNIEnv is abused for passing TestContext.
-template<> struct ScopedPrimitiveArrayTraits<TestType> {
-public:
- static inline void getArrayRegion(JNIEnv*, jTestTypeArray, size_t, size_t, TestType*) {}
-
- static inline TestType* getArrayElements(JNIEnv* env, jTestTypeArray) {
- TestContext* ctx = reinterpret_cast<TestContext*>(env);
- ctx->getArrayElementsCallCount++;
- return ctx->dummyPtr;
- }
-
- static inline void releaseArrayElements(JNIEnv* env, jTestTypeArray, TestType* buffer,
- jint mode) {
- TestContext* ctx = reinterpret_cast<TestContext*>(env);
- if (ctx->dummyPtr == buffer) {
- ctx->releaseArrayElementsCallCount++;
- }
- ctx->elementsUpdated = (mode != JNI_ABORT);
- }
-
- static inline size_t getArrayLength(JNIEnv*, jTestTypeArray array) {
- return array == LARGE_ARRAY ? LARGE_ARRAY_SIZE : SMALL_ARRAY_SIZE;
- }
-
- static inline void fatalError(JNIEnv* env, const char*) {
- reinterpret_cast<TestContext*>(env)->aborted = true;
- }
-
- using ArrayType = jTestTypeArray;
-};
-
-TEST(ScopedPrimitiveArrayTest, testNonNullArray) {
- std::unique_ptr<TestType[]> dummyTestType = std::make_unique<TestType[]>(LARGE_ARRAY_SIZE);
-
- TestContext context;
- context.dummyPtr = dummyTestType.get();
-
- JNIEnv* env = reinterpret_cast<JNIEnv*>(&context);
- {
- context.resetCallCount();
- {
- ScopedArrayRO<TestType, false /* non null */> array(env, SMALL_ARRAY);
- EXPECT_NE(nullptr, array.get());
- EXPECT_EQ(SMALL_ARRAY, array.getJavaArray());
- EXPECT_NE(nullptr, array.begin());
- EXPECT_NE(nullptr, array.end());
- EXPECT_EQ(array.end(), array.begin() + SMALL_ARRAY_SIZE);
- EXPECT_EQ(SMALL_ARRAY_SIZE, array.size());
- }
- EXPECT_EQ(context.getArrayElementsCallCount, context.releaseArrayElementsCallCount);
- EXPECT_FALSE(context.memoryUpdated());
- EXPECT_FALSE(context.aborted);
- }
- {
- context.resetCallCount();
- {
- ScopedArrayRO<TestType, false /* non null */> array(env, LARGE_ARRAY);
-
- EXPECT_EQ(context.dummyPtr, array.get());
- EXPECT_EQ(LARGE_ARRAY, array.getJavaArray());
- EXPECT_EQ(context.dummyPtr, array.begin());
- EXPECT_EQ(context.dummyPtr + LARGE_ARRAY_SIZE, array.end());
- EXPECT_EQ(LARGE_ARRAY_SIZE, array.size());
- }
- EXPECT_EQ(context.getArrayElementsCallCount, context.releaseArrayElementsCallCount);
- EXPECT_FALSE(context.memoryUpdated());
- EXPECT_FALSE(context.aborted);
- }
- {
- context.resetCallCount();
- {
- ScopedArrayRO<TestType, false /* non null */> array(env, nullptr);
- EXPECT_TRUE(context.aborted);
- }
- }
-}
-
-TEST(ScopedPrimitiveArrayTest, testNullableArray) {
- std::unique_ptr<TestType[]> dummyTestType = std::make_unique<TestType[]>(LARGE_ARRAY_SIZE);
-
- TestContext context;
- context.dummyPtr = dummyTestType.get();
-
- JNIEnv* env = reinterpret_cast<JNIEnv*>(&context);
- {
- context.resetCallCount();
- {
- ScopedArrayRO<TestType, true /* nullable */> array(env, SMALL_ARRAY);
- EXPECT_NE(nullptr, array.get());
- EXPECT_EQ(SMALL_ARRAY, array.getJavaArray());
- EXPECT_NE(nullptr, array.begin());
- EXPECT_NE(nullptr, array.end());
- EXPECT_EQ(array.end(), array.begin() + SMALL_ARRAY_SIZE);
- EXPECT_EQ(SMALL_ARRAY_SIZE, (size_t) array.size());
- }
- EXPECT_EQ(context.getArrayElementsCallCount, context.releaseArrayElementsCallCount);
- EXPECT_FALSE(context.memoryUpdated());
- EXPECT_FALSE(context.aborted);
- }
- {
- context.resetCallCount();
- {
- ScopedArrayRO<TestType, true /* nullable */> array(env, LARGE_ARRAY);
- EXPECT_EQ(context.dummyPtr, array.get());
- EXPECT_EQ(LARGE_ARRAY, array.getJavaArray());
- EXPECT_EQ(context.dummyPtr, array.begin());
- EXPECT_EQ(context.dummyPtr + LARGE_ARRAY_SIZE, array.end());
- EXPECT_EQ(LARGE_ARRAY_SIZE, (size_t) array.size());
- }
- EXPECT_EQ(context.getArrayElementsCallCount, context.releaseArrayElementsCallCount);
- EXPECT_FALSE(context.memoryUpdated());
- EXPECT_FALSE(context.aborted);
- }
- {
- context.resetCallCount();
- {
- ScopedArrayRO<TestType, true /* nullable*/> array(env, nullptr);
- EXPECT_EQ(nullptr, array.get());
- EXPECT_EQ(nullptr, array.getJavaArray());
- EXPECT_EQ(nullptr, array.begin());
- EXPECT_EQ(nullptr, array.end());
- EXPECT_EQ(-1, array.size());
- }
- EXPECT_EQ(context.getArrayElementsCallCount, context.releaseArrayElementsCallCount);
- EXPECT_FALSE(context.memoryUpdated());
- EXPECT_FALSE(context.aborted);
- }
-}
-
-TEST(ScopedPrimitiveArrayTest, testArrayRW) {
- std::unique_ptr<TestType[]> dummyTestType = std::make_unique<TestType[]>(LARGE_ARRAY_SIZE);
-
- TestContext context;
- context.dummyPtr = dummyTestType.get();
-
- JNIEnv* env = reinterpret_cast<JNIEnv*>(&context);
- {
- context.resetCallCount();
- {
- ScopedArrayRW<TestType> array(env, SMALL_ARRAY);
- EXPECT_NE(nullptr, array.get());
- EXPECT_EQ(SMALL_ARRAY, array.getJavaArray());
- EXPECT_NE(nullptr, array.begin());
- EXPECT_NE(nullptr, array.end());
- EXPECT_EQ(array.end(), array.begin() + SMALL_ARRAY_SIZE);
- EXPECT_EQ(SMALL_ARRAY_SIZE, (size_t) array.size());
- }
- EXPECT_EQ(context.getArrayElementsCallCount, context.releaseArrayElementsCallCount);
- EXPECT_TRUE(context.memoryUpdated());
- EXPECT_FALSE(context.aborted);
- }
- {
- context.resetCallCount();
- {
- ScopedArrayRW<TestType> array(env, LARGE_ARRAY);
- EXPECT_EQ(context.dummyPtr, array.get());
- EXPECT_EQ(LARGE_ARRAY, array.getJavaArray());
- EXPECT_EQ(context.dummyPtr, array.begin());
- EXPECT_EQ(context.dummyPtr + LARGE_ARRAY_SIZE, array.end());
- EXPECT_EQ(LARGE_ARRAY_SIZE, (size_t) array.size());
- }
- EXPECT_EQ(context.getArrayElementsCallCount, context.releaseArrayElementsCallCount);
- EXPECT_TRUE(context.memoryUpdated());
- EXPECT_FALSE(context.aborted);
- }
- {
- context.resetCallCount();
- {
- ScopedArrayRW<TestType> array(env, nullptr);
- EXPECT_TRUE(context.aborted);
- }
- }
-}