THRIFT-4555 Optionally disable copies of binary fields in constructors, getters and setters.
Client: java
This closes #1540.
diff --git a/lib/java/gradle/generateTestThrift.gradle b/lib/java/gradle/generateTestThrift.gradle
index c347917..2b53739 100644
--- a/lib/java/gradle/generateTestThrift.gradle
+++ b/lib/java/gradle/generateTestThrift.gradle
@@ -24,10 +24,11 @@
ext.genBeanSrc = file("$buildDir/gen-javabean")
ext.genReuseSrc = file("$buildDir/gen-javareuse")
ext.genFullCamelSrc = file("$buildDir/gen-fullcamel")
+ext.genUnsafeSrc = file("$buildDir/gen-unsafe")
// Add the generated code directories to the test source set
sourceSets {
- test.java.srcDirs genSrc, genBeanSrc, genReuseSrc, genFullCamelSrc
+ test.java.srcDirs genSrc, genBeanSrc, genReuseSrc, genFullCamelSrc, genUnsafeSrc
}
// ----------------------------------------------------------------------------
@@ -107,3 +108,12 @@
thriftCompile(it, 'ReuseObjects.thrift', 'java:reuse-objects', genReuseSrc)
}
+
+task generateUnsafeBinariesJava(group: 'Build') {
+ description = 'Generate the thrift gen-unsafebinaries source'
+ generate.dependsOn it
+
+ ext.outputBuffer = new ByteArrayOutputStream()
+
+ thriftCompile(it, 'UnsafeTypes.thrift', 'java:unsafe_binaries', genUnsafeSrc)
+}
diff --git a/lib/java/test/org/apache/thrift/TestUnsafeBinaries.java b/lib/java/test/org/apache/thrift/TestUnsafeBinaries.java
new file mode 100644
index 0000000..d1fc213
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/TestUnsafeBinaries.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.thrift;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import thrift.test.SafeBytes;
+import thrift.test.UnsafeBytes;
+
+// test generating types with un-copied byte[]/ByteBuffer input/output
+//
+public class TestUnsafeBinaries extends TestStruct {
+
+ private static byte[] input() {
+ return new byte[]{1, 1};
+ }
+
+ //
+ // verify that the unsafe_binaries option modifies behavior
+ //
+
+ // constructor doesn't copy
+ public void testUnsafeConstructor() throws Exception {
+
+ byte[] input = input();
+ UnsafeBytes struct = new UnsafeBytes(ByteBuffer.wrap(input));
+
+ input[0] = 2;
+
+ assertTrue(Arrays.equals(
+ new byte[]{2, 1},
+ struct.getBytes())
+ );
+
+ }
+
+ // getter doesn't copy
+ // note: this behavior is the same with/without the flag, but if this default ever changes, the current behavior
+ // should be retained when using this flag
+ public void testUnsafeGetter(){
+ UnsafeBytes struct = new UnsafeBytes(ByteBuffer.wrap(input()));
+
+ byte[] val = struct.getBytes();
+ val[0] = 2;
+
+ assertTrue(Arrays.equals(
+ new byte[]{2, 1},
+ struct.getBytes())
+ );
+
+ }
+
+ // setter doesn't copy
+ public void testUnsafeSetter(){
+ UnsafeBytes struct = new UnsafeBytes();
+
+ byte[] val = input();
+ struct.setBytes(val);
+
+ val[0] = 2;
+
+ assertTrue(Arrays.equals(
+ new byte[]{2, 1},
+ struct.getBytes())
+ );
+
+ }
+
+ // buffer doens't copy
+ public void testUnsafeBufferFor(){
+ UnsafeBytes struct = new UnsafeBytes(ByteBuffer.wrap(input()));
+
+ ByteBuffer val = struct.bufferForBytes();
+ val.array()[0] = 2;
+
+ assertTrue(Arrays.equals(
+ new byte[]{2, 1},
+ struct.getBytes())
+ );
+
+ }
+
+ //
+ // verify that the default generator does not change behavior
+ //
+
+ public void testSafeConstructor() {
+
+ byte[] input = input();
+ SafeBytes struct = new SafeBytes(ByteBuffer.wrap(input));
+
+ input[0] = 2;
+
+ assertTrue(Arrays.equals(
+ new byte[]{1, 1},
+ struct.getBytes())
+ );
+
+ }
+
+ public void testSafeSetter() {
+
+ byte[] input = input();
+ SafeBytes struct = new SafeBytes(ByteBuffer.wrap(input));
+
+ input[0] = 2;
+
+ assertTrue(Arrays.equals(
+ new byte[]{1, 1},
+ struct.getBytes())
+ );
+
+ }
+
+ public void testSafeBufferFor(){
+ SafeBytes struct = new SafeBytes(ByteBuffer.wrap(input()));
+
+ ByteBuffer val = struct.bufferForBytes();
+ val.array()[0] = 2;
+
+ assertTrue(Arrays.equals(
+ new byte[]{1, 1},
+ struct.getBytes())
+ );
+
+ }
+
+}