1 /*
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <vector>
18
19 #include <fbjni/ByteBuffer.h>
20 #include <fbjni/fbjni.h>
21
22 #include "expect.h"
23
24 using namespace facebook::jni;
25
26 namespace {
27
28 std::vector<uint8_t> vec{1, 0, 0, 0};
29
ByteBufferCapacity(alias_ref<JByteBuffer> buffer)30 size_t ByteBufferCapacity(alias_ref<JByteBuffer> buffer) {
31 static auto meth =
32 JByteBuffer::javaClassStatic()->getMethod<int()>("capacity");
33 return meth(buffer);
34 }
35
testDirectByteBuffer(JNIEnv *,jclass)36 jboolean testDirectByteBuffer(JNIEnv*, jclass) {
37 std::vector<uint8_t> vec{5, 4, 3, 2, 1, 0};
38 auto nbb = JByteBuffer::wrapBytes(vec.data(), vec.size());
39
40 EXPECT(ByteBufferCapacity(nbb) == vec.size());
41 EXPECT(nbb->isDirect());
42 EXPECT(nbb->getDirectSize() == vec.size());
43
44 auto bytes = nbb->getDirectBytes();
45
46 for (size_t i = 0; i < vec.size(); i++) {
47 EXPECT(bytes[i] == vec[i]);
48 }
49 return JNI_TRUE;
50 }
51
testEmptyDirectByteBuffer(JNIEnv *,jclass)52 jboolean testEmptyDirectByteBuffer(JNIEnv*, jclass) {
53 uint8_t data;
54 auto nbb = JByteBuffer::wrapBytes(&data, 0);
55
56 EXPECT(ByteBufferCapacity(nbb) == 0);
57 EXPECT(nbb->isDirect());
58 EXPECT(nbb->getDirectSize() == 0);
59
60 return JNI_TRUE;
61 }
62
testRewindBuffer(alias_ref<jobject> self)63 jboolean testRewindBuffer(alias_ref<jobject> self) {
64 std::vector<uint8_t> vec{0, 0, 0, 0, 0, 0, 0, 0};
65 auto nbb = JByteBuffer::wrapBytes(vec.data(), vec.size());
66
67 auto cls = self->getClass();
68 auto writeBytes =
69 cls->getStaticMethod<void(JByteBuffer, jbyte, jbyte, jbyte, jbyte)>(
70 "writeBytes");
71
72 writeBytes(cls, *nbb, 0, 1, 2, 3);
73 nbb->rewind();
74 writeBytes(cls, *nbb, 4, 5, 6, 7);
75
76 EXPECT(vec[0] == 4);
77 EXPECT(vec[1] == 5);
78 EXPECT(vec[2] == 6);
79 EXPECT(vec[3] == 7);
80 EXPECT(vec[4] == 0);
81 EXPECT(vec[5] == 0);
82 EXPECT(vec[6] == 0);
83 EXPECT(vec[7] == 0);
84
85 return JNI_TRUE;
86 }
87
nativeAllocateDirect(alias_ref<jobject> self,int size)88 local_ref<JByteBuffer> nativeAllocateDirect(alias_ref<jobject> self, int size) {
89 return JByteBuffer::allocateDirect(size);
90 }
91
testFloatBuffer(alias_ref<jobject> self,alias_ref<facebook::jni::JBuffer> buffer)92 jboolean testFloatBuffer(
93 alias_ref<jobject> self,
94 alias_ref<facebook::jni::JBuffer> buffer) {
95 EXPECT(buffer->isDirect());
96 EXPECT(buffer->getDirectCapacity() == 5);
97 float* raw = (float*)buffer->getDirectAddress();
98 EXPECT(raw);
99
100 EXPECT(raw[0] == 1);
101 EXPECT(raw[1] == 2);
102 EXPECT(raw[2] == 2.5);
103 EXPECT(raw[3] == 2.75);
104 EXPECT(raw[4] == 3);
105
106 return JNI_TRUE;
107 }
108
nativeByteBufferOrder(alias_ref<jobject> self)109 local_ref<JByteBuffer> nativeByteBufferOrder(alias_ref<jobject> self) {
110 auto nbb = JByteBuffer::wrapBytes(vec.data(), vec.size());
111 return nbb->order(JByteOrder::nativeOrder());
112 }
113
114 } // namespace
115
RegisterByteBufferTests()116 void RegisterByteBufferTests() {
117 registerNatives(
118 "com/facebook/jni/ByteBufferTests",
119 {
120 makeNativeMethod("nativeTestDirectByteBuffer", testDirectByteBuffer),
121 makeNativeMethod(
122 "nativeTestEmptyDirectByteBuffer", testEmptyDirectByteBuffer),
123 makeNativeMethod("nativeTestRewindBuffer", testRewindBuffer),
124 makeNativeMethod("nativeAllocateDirect", nativeAllocateDirect),
125 makeNativeMethod("nativeTestFloatBuffer", testFloatBuffer),
126 makeNativeMethod("nativeByteBufferOrder", nativeByteBufferOrder),
127 });
128 }
129