Skip to content

Commit 06338c4

Browse files
committed
Test channels that return data at different rates
1 parent 46e99a4 commit 06338c4

2 files changed

Lines changed: 97 additions & 22 deletions

File tree

src/test/java/org/apache/commons/io/channels/FileChannelsTest.java

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -44,24 +44,30 @@
4444
public class FileChannelsTest extends AbstractTempDirTest {
4545

4646
enum FileChannelType {
47-
STOCK, PROXY, NON_BLOCKING
47+
STOCK, PROXY, NON_BLOCKING, FIXED_READ_SIZE
4848
}
4949

50+
private static final int LARGE_FILE_SIZE = Integer.getInteger(FileChannelsTest.class.getSimpleName(), 100000);
51+
5052
private static final int SMALL_BUFFER_SIZE = 1024;
5153
private static final String CONTENT = StringUtils.repeat("x", SMALL_BUFFER_SIZE);
5254

5355
@SuppressWarnings("resource") // Caller closes
54-
private static FileChannel getChannel(final FileInputStream inNotEmpty, final FileChannelType fileChannelType) throws IOException {
55-
return wrap(inNotEmpty.getChannel(), fileChannelType);
56+
private static FileChannel getChannel(final FileInputStream inNotEmpty, final FileChannelType fileChannelType, final int readSize) throws IOException {
57+
return wrap(inNotEmpty.getChannel(), fileChannelType, readSize);
58+
}
59+
60+
private static int half(final int bufferSize) {
61+
return Math.max(1, bufferSize / 2);
5662
}
5763

5864
private static boolean isEmpty(final File empty) {
5965
return empty.length() == 0;
6066
}
6167

6268
@SuppressWarnings("resource") // Caller closes
63-
private static FileChannel open(final Path path, final FileChannelType fileChannelType) throws IOException {
64-
return wrap(FileChannel.open(path), fileChannelType);
69+
private static FileChannel open(final Path path, final FileChannelType fileChannelType, final int readSize) throws IOException {
70+
return wrap(FileChannel.open(path), fileChannelType, readSize);
6571
}
6672

6773
private static FileChannel reset(final FileChannel fc) throws IOException {
@@ -72,14 +78,16 @@ private static byte reverse(final byte b) {
7278
return (byte) (~b & 0xff);
7379
}
7480

75-
private static FileChannel wrap(final FileChannel fc, final FileChannelType fileChannelType) throws IOException {
81+
private static FileChannel wrap(final FileChannel fc, final FileChannelType fileChannelType, final int readSize) throws IOException {
7682
switch (fileChannelType) {
7783
case NON_BLOCKING:
7884
return new NonBlockingFileChannelProxy(fc);
7985
case STOCK:
8086
return fc;
8187
case PROXY:
8288
return new FileChannelProxy(fc);
89+
case FIXED_READ_SIZE:
90+
return new FixedReadSizeFileChannelProxy(fc, readSize);
8391
default:
8492
throw new UnsupportedOperationException("Unexpected FileChannelType " + fileChannelType);
8593
}
@@ -98,14 +106,14 @@ private void testContentEquals(final String content1, final String content2, fin
98106
assertNotEquals(FileUtils.checksumCRC32(file1), FileUtils.checksumCRC32(file2));
99107
try (FileInputStream in1 = new FileInputStream(file1);
100108
FileInputStream in2 = new FileInputStream(file2);
101-
FileChannel channel1 = getChannel(in1, fileChannelType);
102-
FileChannel channel2 = getChannel(in2, fileChannelType)) {
109+
FileChannel channel1 = getChannel(in1, fileChannelType, bufferSize);
110+
FileChannel channel2 = getChannel(in2, fileChannelType, half(bufferSize))) {
103111
assertFalse(FileChannels.contentEquals(channel1, channel2, bufferSize));
104112
}
105113
try (FileInputStream in1 = new FileInputStream(file1);
106114
FileInputStream in2 = new FileInputStream(file2);
107-
FileChannel channel1 = getChannel(in1, fileChannelType);
108-
FileChannel channel2 = getChannel(in2, fileChannelType)) {
115+
FileChannel channel1 = getChannel(in1, fileChannelType, bufferSize);
116+
FileChannel channel2 = getChannel(in2, fileChannelType, half(bufferSize))) {
109117
assertTrue(FileChannels.contentEquals(channel1, channel1, bufferSize));
110118
assertTrue(FileChannels.contentEquals(channel2, channel2, bufferSize));
111119
}
@@ -141,8 +149,8 @@ public void testContentEqualsEmpty(
141149
assertNotEquals(FileUtils.checksumCRC32(empty), FileUtils.checksumCRC32(notEmpty));
142150
try (FileInputStream inEmpty = new FileInputStream(empty);
143151
FileInputStream inNotEmpty = new FileInputStream(notEmpty);
144-
FileChannel channelEmpty = getChannel(inEmpty, fileChannelType);
145-
FileChannel channelNotEmpty = getChannel(inNotEmpty, fileChannelType)) {
152+
FileChannel channelEmpty = getChannel(inEmpty, fileChannelType, bufferSize);
153+
FileChannel channelNotEmpty = getChannel(inNotEmpty, fileChannelType, half(bufferSize))) {
146154
assertFalse(FileChannels.contentEquals(channelEmpty, channelNotEmpty, bufferSize));
147155
assertFalse(FileChannels.contentEquals(null, channelNotEmpty, bufferSize));
148156
assertFalse(FileChannels.contentEquals(channelNotEmpty, null, bufferSize));
@@ -163,7 +171,7 @@ public void testContentEqualsFileChannel(
163171
final Path bigFile3 = Files.createTempFile(getClass().getSimpleName(), "-3.bin");
164172
try {
165173
// This length must match any restriction from the Surefire configuration.
166-
final int newLength = 2_000_000;
174+
final int newLength = LARGE_FILE_SIZE;
167175
final byte[] bytes1 = new byte[newLength];
168176
final byte[] bytes2 = new byte[newLength];
169177
// Make sure bytes1 and bytes2 are different despite the shuffle
@@ -173,7 +181,7 @@ public void testContentEqualsFileChannel(
173181
bytes2[0] = 2;
174182
Files.write(bigFile1, bytes1);
175183
Files.write(bigFile2, bytes2);
176-
try (FileChannel fc1 = open(bigFile1, fileChannelType); FileChannel fc2 = open(bigFile2, fileChannelType)) {
184+
try (FileChannel fc1 = open(bigFile1, fileChannelType, bufferSize); FileChannel fc2 = open(bigFile2, fileChannelType, half(bufferSize))) {
177185
assertFalse(FileChannels.contentEquals(fc1, fc2, bufferSize));
178186
assertFalse(FileChannels.contentEquals(reset(fc2), reset(fc1), bufferSize));
179187
assertTrue(FileChannels.contentEquals(reset(fc1), reset(fc1), bufferSize));
@@ -183,7 +191,7 @@ public void testContentEqualsFileChannel(
183191
final int last = bytes3.length - 1;
184192
bytes3[last] = reverse(bytes3[last]);
185193
Files.write(bigFile3, bytes3);
186-
try (FileChannel fc1 = open(bigFile1, fileChannelType); FileChannel fc3 = open(bigFile3, fileChannelType)) {
194+
try (FileChannel fc1 = open(bigFile1, fileChannelType, bufferSize); FileChannel fc3 = open(bigFile3, fileChannelType, half(bufferSize))) {
187195
assertFalse(FileChannels.contentEquals(fc1, fc3, bufferSize));
188196
assertFalse(FileChannels.contentEquals(reset(fc3), reset(fc1), bufferSize));
189197
// Test just the last byte
@@ -194,7 +202,7 @@ public void testContentEqualsFileChannel(
194202
// Make the LAST byte equal.
195203
bytes3 = bytes1.clone();
196204
Files.write(bigFile3, bytes3);
197-
try (FileChannel fc1 = open(bigFile1, fileChannelType); FileChannel fc3 = open(bigFile3, fileChannelType)) {
205+
try (FileChannel fc1 = open(bigFile1, fileChannelType, bufferSize); FileChannel fc3 = open(bigFile3, fileChannelType, half(bufferSize))) {
198206
// Test just the last byte
199207
fc1.position(last);
200208
fc3.position(last);
@@ -205,7 +213,7 @@ public void testContentEqualsFileChannel(
205213
final int middle = bytes3.length / 2;
206214
bytes3[middle] = reverse(bytes3[middle]);
207215
Files.write(bigFile3, bytes3);
208-
try (FileChannel fc1 = open(bigFile1, fileChannelType); FileChannel fc3 = open(bigFile3, fileChannelType)) {
216+
try (FileChannel fc1 = open(bigFile1, fileChannelType, bufferSize); FileChannel fc3 = open(bigFile3, fileChannelType, half(bufferSize))) {
209217
assertFalse(FileChannels.contentEquals(fc1, fc3, bufferSize));
210218
assertFalse(FileChannels.contentEquals(reset(fc3), reset(fc1), bufferSize));
211219
}
@@ -226,7 +234,7 @@ public void testContentEqualsSeekableByteChannel(
226234
final Path bigFile3 = Files.createTempFile(getClass().getSimpleName(), "-3.bin");
227235
try {
228236
// This length must match any restriction from the Surefire configuration.
229-
final int newLength = 1_000_000;
237+
final int newLength = LARGE_FILE_SIZE;
230238
final byte[] bytes1 = new byte[newLength];
231239
final byte[] bytes2 = new byte[newLength];
232240
// Make sure bytes1 and bytes2 are different despite the shuffle
@@ -236,7 +244,7 @@ public void testContentEqualsSeekableByteChannel(
236244
bytes2[0] = 2;
237245
Files.write(bigFile1, bytes1);
238246
Files.write(bigFile2, bytes2);
239-
try (FileChannel fc1 = open(bigFile1, fileChannelType1); FileChannel fc2 = open(bigFile2, fileChannelType2)) {
247+
try (FileChannel fc1 = open(bigFile1, fileChannelType1, bufferSize); FileChannel fc2 = open(bigFile2, fileChannelType2, half(bufferSize))) {
240248
assertFalse(FileChannels.contentEquals((SeekableByteChannel) fc1, fc2, bufferSize));
241249
assertFalse(FileChannels.contentEquals((SeekableByteChannel) reset(fc2), reset(fc1), bufferSize));
242250
assertTrue(FileChannels.contentEquals((SeekableByteChannel) reset(fc1), reset(fc1), bufferSize));
@@ -246,7 +254,7 @@ public void testContentEqualsSeekableByteChannel(
246254
final int last = bytes3.length - 1;
247255
bytes3[last] = reverse(bytes3[last]);
248256
Files.write(bigFile3, bytes3);
249-
try (FileChannel fc1 = open(bigFile1, fileChannelType1); FileChannel fc3 = open(bigFile3, fileChannelType2)) {
257+
try (FileChannel fc1 = open(bigFile1, fileChannelType1, bufferSize); FileChannel fc3 = open(bigFile3, fileChannelType2, half(bufferSize))) {
250258
assertFalse(FileChannels.contentEquals((SeekableByteChannel) fc1, fc3, bufferSize));
251259
assertFalse(FileChannels.contentEquals((SeekableByteChannel) reset(fc3), reset(fc1), bufferSize));
252260
// Test just the last byte
@@ -257,7 +265,7 @@ public void testContentEqualsSeekableByteChannel(
257265
// Make the LAST byte equal.
258266
bytes3 = bytes1.clone();
259267
Files.write(bigFile3, bytes3);
260-
try (FileChannel fc1 = open(bigFile1, fileChannelType1); FileChannel fc3 = open(bigFile3, fileChannelType2)) {
268+
try (FileChannel fc1 = open(bigFile1, fileChannelType1, bufferSize); FileChannel fc3 = open(bigFile3, fileChannelType2, half(bufferSize))) {
261269
// Test just the last byte
262270
fc1.position(last);
263271
fc3.position(last);
@@ -268,7 +276,7 @@ public void testContentEqualsSeekableByteChannel(
268276
final int middle = bytes3.length / 2;
269277
bytes3[middle] = reverse(bytes3[middle]);
270278
Files.write(bigFile3, bytes3);
271-
try (FileChannel fc1 = open(bigFile1, fileChannelType1); FileChannel fc3 = open(bigFile3, fileChannelType2)) {
279+
try (FileChannel fc1 = open(bigFile1, fileChannelType1, bufferSize); FileChannel fc3 = open(bigFile3, fileChannelType2, half(bufferSize))) {
272280
assertFalse(FileChannels.contentEquals((SeekableByteChannel) fc1, fc3, bufferSize));
273281
assertFalse(FileChannels.contentEquals((SeekableByteChannel) reset(fc3), reset(fc1), bufferSize));
274282
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.commons.io.channels;
19+
20+
import java.io.IOException;
21+
import java.nio.ByteBuffer;
22+
import java.nio.channels.FileChannel;
23+
24+
/**
25+
* Always reads the same amount of bytes on each call or less.
26+
*/
27+
class FixedReadSizeFileChannelProxy extends FileChannelProxy {
28+
29+
final int readSize;
30+
31+
FixedReadSizeFileChannelProxy(final FileChannel fileChannel, final int readSize) {
32+
super(fileChannel);
33+
if (readSize < 1) {
34+
throw new IllegalArgumentException("readSize: " + readSize);
35+
}
36+
this.readSize = readSize;
37+
}
38+
39+
@Override
40+
public int read(final ByteBuffer dst) throws IOException {
41+
final int limit = dst.limit();
42+
dst.limit(Math.min(readSize, dst.limit()));
43+
final int read = super.read(dst);
44+
if (read > readSize) {
45+
throw new IllegalStateException("Programming error.");
46+
}
47+
dst.limit(limit);
48+
return read;
49+
}
50+
51+
@Override
52+
public int read(final ByteBuffer dst, final long position) throws IOException {
53+
final int limit = dst.limit();
54+
dst.limit(Math.min(readSize, dst.limit()));
55+
final int read = super.read(dst, position);
56+
if (read > readSize) {
57+
throw new IllegalStateException("Programming error.");
58+
}
59+
dst.limit(limit);
60+
return read;
61+
}
62+
63+
@Override
64+
public long read(final ByteBuffer[] dsts, final int offset, final int length) throws IOException {
65+
throw new UnsupportedOperationException();
66+
}
67+
}

0 commit comments

Comments
 (0)