You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2025/03/03 16:13:14 UTC
(commons-io) 01/02: Test channels that return data at different rates
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-io.git
commit 06338c4481fb8b2c824361f22b994a878ac7a3c8
Author: Gary D. Gregory <ga...@gmail.com>
AuthorDate: Mon Mar 3 11:08:34 2025 -0500
Test channels that return data at different rates
---
.../commons/io/channels/FileChannelsTest.java | 52 ++++++++++-------
.../io/channels/FixedReadSizeFileChannelProxy.java | 67 ++++++++++++++++++++++
2 files changed, 97 insertions(+), 22 deletions(-)
diff --git a/src/test/java/org/apache/commons/io/channels/FileChannelsTest.java b/src/test/java/org/apache/commons/io/channels/FileChannelsTest.java
index 7ba6ee8bc..46f223d16 100644
--- a/src/test/java/org/apache/commons/io/channels/FileChannelsTest.java
+++ b/src/test/java/org/apache/commons/io/channels/FileChannelsTest.java
@@ -44,15 +44,21 @@
public class FileChannelsTest extends AbstractTempDirTest {
enum FileChannelType {
- STOCK, PROXY, NON_BLOCKING
+ STOCK, PROXY, NON_BLOCKING, FIXED_READ_SIZE
}
+ private static final int LARGE_FILE_SIZE = Integer.getInteger(FileChannelsTest.class.getSimpleName(), 100000);
+
private static final int SMALL_BUFFER_SIZE = 1024;
private static final String CONTENT = StringUtils.repeat("x", SMALL_BUFFER_SIZE);
@SuppressWarnings("resource") // Caller closes
- private static FileChannel getChannel(final FileInputStream inNotEmpty, final FileChannelType fileChannelType) throws IOException {
- return wrap(inNotEmpty.getChannel(), fileChannelType);
+ private static FileChannel getChannel(final FileInputStream inNotEmpty, final FileChannelType fileChannelType, final int readSize) throws IOException {
+ return wrap(inNotEmpty.getChannel(), fileChannelType, readSize);
+ }
+
+ private static int half(final int bufferSize) {
+ return Math.max(1, bufferSize / 2);
}
private static boolean isEmpty(final File empty) {
@@ -60,8 +66,8 @@ private static boolean isEmpty(final File empty) {
}
@SuppressWarnings("resource") // Caller closes
- private static FileChannel open(final Path path, final FileChannelType fileChannelType) throws IOException {
- return wrap(FileChannel.open(path), fileChannelType);
+ private static FileChannel open(final Path path, final FileChannelType fileChannelType, final int readSize) throws IOException {
+ return wrap(FileChannel.open(path), fileChannelType, readSize);
}
private static FileChannel reset(final FileChannel fc) throws IOException {
@@ -72,7 +78,7 @@ private static byte reverse(final byte b) {
return (byte) (~b & 0xff);
}
- private static FileChannel wrap(final FileChannel fc, final FileChannelType fileChannelType) throws IOException {
+ private static FileChannel wrap(final FileChannel fc, final FileChannelType fileChannelType, final int readSize) throws IOException {
switch (fileChannelType) {
case NON_BLOCKING:
return new NonBlockingFileChannelProxy(fc);
@@ -80,6 +86,8 @@ private static FileChannel wrap(final FileChannel fc, final FileChannelType file
return fc;
case PROXY:
return new FileChannelProxy(fc);
+ case FIXED_READ_SIZE:
+ return new FixedReadSizeFileChannelProxy(fc, readSize);
default:
throw new UnsupportedOperationException("Unexpected FileChannelType " + fileChannelType);
}
@@ -98,14 +106,14 @@ private void testContentEquals(final String content1, final String content2, fin
assertNotEquals(FileUtils.checksumCRC32(file1), FileUtils.checksumCRC32(file2));
try (FileInputStream in1 = new FileInputStream(file1);
FileInputStream in2 = new FileInputStream(file2);
- FileChannel channel1 = getChannel(in1, fileChannelType);
- FileChannel channel2 = getChannel(in2, fileChannelType)) {
+ FileChannel channel1 = getChannel(in1, fileChannelType, bufferSize);
+ FileChannel channel2 = getChannel(in2, fileChannelType, half(bufferSize))) {
assertFalse(FileChannels.contentEquals(channel1, channel2, bufferSize));
}
try (FileInputStream in1 = new FileInputStream(file1);
FileInputStream in2 = new FileInputStream(file2);
- FileChannel channel1 = getChannel(in1, fileChannelType);
- FileChannel channel2 = getChannel(in2, fileChannelType)) {
+ FileChannel channel1 = getChannel(in1, fileChannelType, bufferSize);
+ FileChannel channel2 = getChannel(in2, fileChannelType, half(bufferSize))) {
assertTrue(FileChannels.contentEquals(channel1, channel1, bufferSize));
assertTrue(FileChannels.contentEquals(channel2, channel2, bufferSize));
}
@@ -141,8 +149,8 @@ public void testContentEqualsEmpty(
assertNotEquals(FileUtils.checksumCRC32(empty), FileUtils.checksumCRC32(notEmpty));
try (FileInputStream inEmpty = new FileInputStream(empty);
FileInputStream inNotEmpty = new FileInputStream(notEmpty);
- FileChannel channelEmpty = getChannel(inEmpty, fileChannelType);
- FileChannel channelNotEmpty = getChannel(inNotEmpty, fileChannelType)) {
+ FileChannel channelEmpty = getChannel(inEmpty, fileChannelType, bufferSize);
+ FileChannel channelNotEmpty = getChannel(inNotEmpty, fileChannelType, half(bufferSize))) {
assertFalse(FileChannels.contentEquals(channelEmpty, channelNotEmpty, bufferSize));
assertFalse(FileChannels.contentEquals(null, channelNotEmpty, bufferSize));
assertFalse(FileChannels.contentEquals(channelNotEmpty, null, bufferSize));
@@ -163,7 +171,7 @@ public void testContentEqualsFileChannel(
final Path bigFile3 = Files.createTempFile(getClass().getSimpleName(), "-3.bin");
try {
// This length must match any restriction from the Surefire configuration.
- final int newLength = 2_000_000;
+ final int newLength = LARGE_FILE_SIZE;
final byte[] bytes1 = new byte[newLength];
final byte[] bytes2 = new byte[newLength];
// Make sure bytes1 and bytes2 are different despite the shuffle
@@ -173,7 +181,7 @@ public void testContentEqualsFileChannel(
bytes2[0] = 2;
Files.write(bigFile1, bytes1);
Files.write(bigFile2, bytes2);
- try (FileChannel fc1 = open(bigFile1, fileChannelType); FileChannel fc2 = open(bigFile2, fileChannelType)) {
+ try (FileChannel fc1 = open(bigFile1, fileChannelType, bufferSize); FileChannel fc2 = open(bigFile2, fileChannelType, half(bufferSize))) {
assertFalse(FileChannels.contentEquals(fc1, fc2, bufferSize));
assertFalse(FileChannels.contentEquals(reset(fc2), reset(fc1), bufferSize));
assertTrue(FileChannels.contentEquals(reset(fc1), reset(fc1), bufferSize));
@@ -183,7 +191,7 @@ public void testContentEqualsFileChannel(
final int last = bytes3.length - 1;
bytes3[last] = reverse(bytes3[last]);
Files.write(bigFile3, bytes3);
- try (FileChannel fc1 = open(bigFile1, fileChannelType); FileChannel fc3 = open(bigFile3, fileChannelType)) {
+ try (FileChannel fc1 = open(bigFile1, fileChannelType, bufferSize); FileChannel fc3 = open(bigFile3, fileChannelType, half(bufferSize))) {
assertFalse(FileChannels.contentEquals(fc1, fc3, bufferSize));
assertFalse(FileChannels.contentEquals(reset(fc3), reset(fc1), bufferSize));
// Test just the last byte
@@ -194,7 +202,7 @@ public void testContentEqualsFileChannel(
// Make the LAST byte equal.
bytes3 = bytes1.clone();
Files.write(bigFile3, bytes3);
- try (FileChannel fc1 = open(bigFile1, fileChannelType); FileChannel fc3 = open(bigFile3, fileChannelType)) {
+ try (FileChannel fc1 = open(bigFile1, fileChannelType, bufferSize); FileChannel fc3 = open(bigFile3, fileChannelType, half(bufferSize))) {
// Test just the last byte
fc1.position(last);
fc3.position(last);
@@ -205,7 +213,7 @@ public void testContentEqualsFileChannel(
final int middle = bytes3.length / 2;
bytes3[middle] = reverse(bytes3[middle]);
Files.write(bigFile3, bytes3);
- try (FileChannel fc1 = open(bigFile1, fileChannelType); FileChannel fc3 = open(bigFile3, fileChannelType)) {
+ try (FileChannel fc1 = open(bigFile1, fileChannelType, bufferSize); FileChannel fc3 = open(bigFile3, fileChannelType, half(bufferSize))) {
assertFalse(FileChannels.contentEquals(fc1, fc3, bufferSize));
assertFalse(FileChannels.contentEquals(reset(fc3), reset(fc1), bufferSize));
}
@@ -226,7 +234,7 @@ public void testContentEqualsSeekableByteChannel(
final Path bigFile3 = Files.createTempFile(getClass().getSimpleName(), "-3.bin");
try {
// This length must match any restriction from the Surefire configuration.
- final int newLength = 1_000_000;
+ final int newLength = LARGE_FILE_SIZE;
final byte[] bytes1 = new byte[newLength];
final byte[] bytes2 = new byte[newLength];
// Make sure bytes1 and bytes2 are different despite the shuffle
@@ -236,7 +244,7 @@ public void testContentEqualsSeekableByteChannel(
bytes2[0] = 2;
Files.write(bigFile1, bytes1);
Files.write(bigFile2, bytes2);
- try (FileChannel fc1 = open(bigFile1, fileChannelType1); FileChannel fc2 = open(bigFile2, fileChannelType2)) {
+ try (FileChannel fc1 = open(bigFile1, fileChannelType1, bufferSize); FileChannel fc2 = open(bigFile2, fileChannelType2, half(bufferSize))) {
assertFalse(FileChannels.contentEquals((SeekableByteChannel) fc1, fc2, bufferSize));
assertFalse(FileChannels.contentEquals((SeekableByteChannel) reset(fc2), reset(fc1), bufferSize));
assertTrue(FileChannels.contentEquals((SeekableByteChannel) reset(fc1), reset(fc1), bufferSize));
@@ -246,7 +254,7 @@ public void testContentEqualsSeekableByteChannel(
final int last = bytes3.length - 1;
bytes3[last] = reverse(bytes3[last]);
Files.write(bigFile3, bytes3);
- try (FileChannel fc1 = open(bigFile1, fileChannelType1); FileChannel fc3 = open(bigFile3, fileChannelType2)) {
+ try (FileChannel fc1 = open(bigFile1, fileChannelType1, bufferSize); FileChannel fc3 = open(bigFile3, fileChannelType2, half(bufferSize))) {
assertFalse(FileChannels.contentEquals((SeekableByteChannel) fc1, fc3, bufferSize));
assertFalse(FileChannels.contentEquals((SeekableByteChannel) reset(fc3), reset(fc1), bufferSize));
// Test just the last byte
@@ -257,7 +265,7 @@ public void testContentEqualsSeekableByteChannel(
// Make the LAST byte equal.
bytes3 = bytes1.clone();
Files.write(bigFile3, bytes3);
- try (FileChannel fc1 = open(bigFile1, fileChannelType1); FileChannel fc3 = open(bigFile3, fileChannelType2)) {
+ try (FileChannel fc1 = open(bigFile1, fileChannelType1, bufferSize); FileChannel fc3 = open(bigFile3, fileChannelType2, half(bufferSize))) {
// Test just the last byte
fc1.position(last);
fc3.position(last);
@@ -268,7 +276,7 @@ public void testContentEqualsSeekableByteChannel(
final int middle = bytes3.length / 2;
bytes3[middle] = reverse(bytes3[middle]);
Files.write(bigFile3, bytes3);
- try (FileChannel fc1 = open(bigFile1, fileChannelType1); FileChannel fc3 = open(bigFile3, fileChannelType2)) {
+ try (FileChannel fc1 = open(bigFile1, fileChannelType1, bufferSize); FileChannel fc3 = open(bigFile3, fileChannelType2, half(bufferSize))) {
assertFalse(FileChannels.contentEquals((SeekableByteChannel) fc1, fc3, bufferSize));
assertFalse(FileChannels.contentEquals((SeekableByteChannel) reset(fc3), reset(fc1), bufferSize));
}
diff --git a/src/test/java/org/apache/commons/io/channels/FixedReadSizeFileChannelProxy.java b/src/test/java/org/apache/commons/io/channels/FixedReadSizeFileChannelProxy.java
new file mode 100644
index 000000000..132626d30
--- /dev/null
+++ b/src/test/java/org/apache/commons/io/channels/FixedReadSizeFileChannelProxy.java
@@ -0,0 +1,67 @@
+/*
+ * 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.commons.io.channels;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+
+/**
+ * Always reads the same amount of bytes on each call or less.
+ */
+class FixedReadSizeFileChannelProxy extends FileChannelProxy {
+
+ final int readSize;
+
+ FixedReadSizeFileChannelProxy(final FileChannel fileChannel, final int readSize) {
+ super(fileChannel);
+ if (readSize < 1) {
+ throw new IllegalArgumentException("readSize: " + readSize);
+ }
+ this.readSize = readSize;
+ }
+
+ @Override
+ public int read(final ByteBuffer dst) throws IOException {
+ final int limit = dst.limit();
+ dst.limit(Math.min(readSize, dst.limit()));
+ final int read = super.read(dst);
+ if (read > readSize) {
+ throw new IllegalStateException("Programming error.");
+ }
+ dst.limit(limit);
+ return read;
+ }
+
+ @Override
+ public int read(final ByteBuffer dst, final long position) throws IOException {
+ final int limit = dst.limit();
+ dst.limit(Math.min(readSize, dst.limit()));
+ final int read = super.read(dst, position);
+ if (read > readSize) {
+ throw new IllegalStateException("Programming error.");
+ }
+ dst.limit(limit);
+ return read;
+ }
+
+ @Override
+ public long read(final ByteBuffer[] dsts, final int offset, final int length) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+}