1
1
/*
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.
3
3
*
4
4
* This program and the accompanying materials are made available under the
5
5
* terms of the Eclipse Public License v. 2.0, which is available at
16
16
17
17
package jakarta .mail .util ;
18
18
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 ;
20
23
21
24
import java .io .File ;
22
25
import java .io .IOException ;
23
26
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 ;
24
33
25
- import static org .junit .Assert . fail ;
34
+ import org .junit .Test ;
26
35
27
36
/**
28
37
* Please note:
@@ -62,4 +71,85 @@ public void testGrandChild() throws Exception {
62
71
file .delete ();
63
72
}
64
73
}
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
+ }
65
155
}
0 commit comments