Skip to content

Commit 37e36ce

Browse files
committed
Adding SharedFileInputStream tests
Signed-off-by: Jorge Bescos Gascon <jorge.bescos.gascon@oracle.com>
1 parent f4684d5 commit 37e36ce

File tree

4 files changed

+124
-23
lines changed

4 files changed

+124
-23
lines changed

api/src/main/java/jakarta/mail/util/SharedFileInputStream.java

+20-20
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public class SharedFileInputStream extends BufferedInputStream
7676
*/
7777
static class SharedFile implements AutoCloseable {
7878
private int cnt;
79-
private RandomAccessFile in;
79+
RandomAccessFile in;
8080

8181
SharedFile(String file) throws IOException {
8282
this.in = new RandomAccessFile(file, "r");
@@ -256,10 +256,10 @@ private int read1(byte[] b, int off, int len) throws IOException {
256256
int avail = count - pos;
257257
if (avail <= 0) {
258258
if (false) {
259-
/* If the requested length is at least as large as the buffer, and
260-
if there is no mark/reset activity, do not bother to copy the
261-
bytes into the local buffer. In this way buffered streams will
262-
cascade harmlessly. */
259+
/* If the requested length is at least as large as the buffer, and
260+
if there is no mark/reset activity, do not bother to copy the
261+
bytes into the local buffer. In this way buffered streams will
262+
cascade harmlessly. */
263263
if (len >= buf.length && markpos < 0) {
264264
// XXX - seek, update bufpos - how?
265265
return in.read(b, off, len);
@@ -328,10 +328,10 @@ public synchronized long skip(long n) throws IOException {
328328

329329
if (avail <= 0) {
330330
// If no mark position set then don't keep in buffer
331-
/*
331+
/*
332332
if (markpos <0)
333333
return in.skip(n);
334-
*/
334+
*/
335335

336336
// Fill in buffer to save bytes for reset
337337
fill();
@@ -439,7 +439,7 @@ public void close() throws IOException {
439439
@Override
440440
public long getPosition() {
441441
//System.out.println("getPosition: start " + start + " pos " + pos
442-
// + " bufpos " + bufpos + " = " + (bufpos + pos - start));
442+
// + " bufpos " + bufpos + " = " + (bufpos + pos - start));
443443
if (in == null)
444444
throw new RuntimeException("Stream closed");
445445
return bufpos + pos - start;
@@ -473,18 +473,18 @@ public synchronized InputStream newStream(long start, long end) {
473473
// for testing...
474474
/*
475475
public static void main(String[] argv) throws Exception {
476-
SharedFileInputStream is = new SharedFileInputStream(argv[0]);
477-
java.util.Random r = new java.util.Random();
478-
int b;
479-
while ((b = is.read()) >= 0) {
480-
System.out.write(b);
481-
if (r.nextDouble() < 0.3) {
482-
InputStream is2 = is.newStream(is.getPosition(), -1);
483-
int b2;
484-
while ((b2 = is2.read()) >= 0)
485-
;
486-
}
487-
}
476+
SharedFileInputStream is = new SharedFileInputStream(argv[0]);
477+
java.util.Random r = new java.util.Random();
478+
int b;
479+
while ((b = is.read()) >= 0) {
480+
System.out.write(b);
481+
if (r.nextDouble() < 0.3) {
482+
InputStream is2 = is.newStream(is.getPosition(), -1);
483+
int b2;
484+
while ((b2 = is2.read()) >= 0)
485+
;
486+
}
487+
}
488488
}
489489
*/
490490
}

api/src/test/java/jakarta/mail/util/SharedFileInputStreamTest.java

+93-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -16,13 +16,22 @@
1616

1717
package jakarta.mail.util;
1818

19-
import org.junit.Test;
19+
import static org.junit.Assert.assertEquals;
20+
import static org.junit.Assert.fail;
21+
22+
import jakarta.mail.util.SharedFileInputStream.SharedFile;
2023

2124
import java.io.File;
2225
import java.io.IOException;
2326
import java.io.InputStream;
27+
import java.io.RandomAccessFile;
28+
import java.lang.ref.PhantomReference;
29+
import java.lang.ref.Reference;
30+
import java.lang.ref.ReferenceQueue;
31+
import java.lang.reflect.Field;
32+
import java.util.concurrent.TimeoutException;
2433

25-
import static org.junit.Assert.fail;
34+
import org.junit.Test;
2635

2736
/**
2837
* Please note:
@@ -62,4 +71,85 @@ public void testGrandChild() throws Exception {
6271
file.delete();
6372
}
6473
}
74+
75+
@Test
76+
public void testOpenIfOneOpened() throws Exception {
77+
File file = new File(SharedFileInputStreamTest.class.getResource("/jakarta/mail/util/sharedinputstream.txt").toURI());
78+
SharedFileInputStream in0 = null;
79+
SharedFileInputStream in1 = null;
80+
try (SharedFileInputStream in = new SharedFileInputStream(file)) {
81+
in0 = (SharedFileInputStream) in.newStream(0, 6);
82+
in1 = (SharedFileInputStream) in.newStream(6, 12);
83+
}
84+
RandomAccessFile ra0 = getRandomAccessFile(in0);
85+
RandomAccessFile ra1 = getRandomAccessFile(in1);
86+
// It is the same instance
87+
assertEquals(ra0, ra1);
88+
// RandomAccessFile still be open
89+
in1.close();
90+
assertEquals(false, isClosed(ra1));
91+
in0.close();
92+
// All SharedFileInputStream are closed, so RandomAccessFile gets closed too
93+
assertEquals(true, isClosed(ra1));
94+
}
95+
96+
@Test
97+
public void testGC() throws Exception {
98+
File file = new File(SharedFileInputStreamTest.class.getResource("/jakarta/mail/util/sharedinputstream.txt").toURI());
99+
SharedFileInputStream in = new SharedFileInputStream(file);
100+
GCUtil gcUtil = new GCUtil(in);
101+
SharedFileInputStream in0 = (SharedFileInputStream) in.newStream(0, 6);
102+
in.close();
103+
in = null;
104+
gcUtil.waitTillGCed(1000);
105+
gcUtil = new GCUtil(in0);
106+
SharedFileInputStream in1 = (SharedFileInputStream) in0.newStream(6, 12);
107+
assertEquals("test0\n", new String(in0.readAllBytes()));
108+
in0.close();
109+
in0 = null;
110+
gcUtil.waitTillGCed(1000);
111+
assertEquals("test1\n", new String(in1.readAllBytes()));
112+
in1.close();
113+
}
114+
115+
private RandomAccessFile getRandomAccessFile(SharedFileInputStream in) throws Exception {
116+
Field f1 = SharedFileInputStream.class.getDeclaredField("sf");
117+
f1.setAccessible(true);
118+
SharedFile rin = (SharedFile) f1.get(in);
119+
RandomAccessFile rf = rin.in;
120+
return rf;
121+
}
122+
123+
private boolean isClosed(RandomAccessFile rf) throws Exception {
124+
try {
125+
rf.readByte();
126+
return false;
127+
} catch (IOException e) {
128+
return true;
129+
}
130+
}
131+
132+
private static class GCUtil {
133+
134+
private final ReferenceQueue<Object> rq = new ReferenceQueue<>();
135+
private final PhantomReference<Object> phantomRef;
136+
137+
private GCUtil(Object ref) {
138+
phantomRef = new PhantomReference<>(ref, rq);
139+
}
140+
141+
private void waitTillGCed(long timeout) throws Exception {
142+
Reference<? extends Object> gced;
143+
long time = 0;
144+
long sleep = 100;
145+
while ((gced = rq.poll()) != phantomRef) {
146+
Thread.sleep(sleep);
147+
time = time + sleep;
148+
if (time >= timeout) {
149+
throw new TimeoutException("Instance not GCed after " + timeout + " millis");
150+
}
151+
System.gc();
152+
}
153+
}
154+
}
65155
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
test0
2+
test1
3+
test2
4+
test3
5+
test4
6+
test5
7+
test6
8+
test7
9+
test8
10+
test9

copyright-exclude

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ mail/src/test/resources/jakarta/mail/internet/paramdata
2424
mail/src/test/resources/jakarta/mail/internet/paramdatanostrict
2525
api/src/test/resources/jakarta/mail/internet/tokenlist
2626
api/src/test/resources/jakarta/mail/internet/addrlist
27+
api/src/test/resources/jakarta/mail/util/sharedinputstream.txt
2728
mail/src/test/resources/jakarta/mail/internet/MailDateFormat_old.ser
2829
mail/src/test/resources/jakarta/mail/internet/MailDateFormat_new.ser
2930
mail/src/test/resources/com/sun/mail/test/keystore.jks

0 commit comments

Comments
 (0)