1 /*
2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /* @test
25  * @bug 8204310
26  * @summary Check how FileChannel behaves if the file size/offset change via
27  *          RAF.setLength() and other methods.
28  * @run main TruncateRAF
29  */
30 
31 import java.io.File;
32 import java.io.RandomAccessFile;
33 import java.io.IOException;
34 import java.nio.ByteBuffer;
35 import java.nio.channels.FileChannel;
36 
37 public class TruncateRAF {
38 
checkState(RandomAccessFile raf, FileChannel fch, long expectedOffset, long expectedLength)39     static void checkState(RandomAccessFile raf, FileChannel fch,
40             long expectedOffset, long expectedLength)
41         throws IOException
42     {
43         long rafLength = raf.length();
44         long rafOffset = raf.getFilePointer();
45         long fchLength = fch.size();
46         long fchOffset = fch.position();
47 
48         if (rafLength != expectedLength)
49             throw new RuntimeException("rafLength (" + rafLength + ") != " +
50                     "expectedLength (" + expectedLength + ")");
51         if (rafOffset != expectedOffset)
52             throw new RuntimeException("rafOffset (" + rafOffset + ") != " +
53                     "expectedOffset (" + expectedOffset + ")");
54         if (fchLength != expectedLength)
55             throw new RuntimeException("fchLength (" + fchLength + ") != " +
56                     "expectedLength (" + expectedLength + ")");
57         if (fchOffset != expectedOffset)
58             throw new RuntimeException("fchOffset (" + fchOffset + ") != " +
59                     "expectedOffset (" + expectedOffset + ")");
60     }
61 
main(String[] args)62     public static void main(String[] args) throws Throwable {
63         File file = new File("tmp");
64         try (RandomAccessFile raf = new RandomAccessFile(file, "rw");
65              FileChannel fch = raf.getChannel()) {
66 
67             // initially empty
68             checkState(raf, fch, 0, 0);
69 
70             // seeking beyond EOF
71             raf.seek(42);
72             checkState(raf, fch, 42, 0);
73 
74             // seeking beyond EOF
75             fch.position(84);
76             checkState(raf, fch, 84, 0);
77 
78             // writing at offset beyond EOF
79             raf.write(1);
80             checkState(raf, fch, 85, 85);
81 
82             // truncating
83             raf.setLength(63);
84             checkState(raf, fch, 63, 63);
85 
86             // writing at EOF
87             fch.write(ByteBuffer.wrap(new byte[1]));
88             checkState(raf, fch, 64, 64);
89 
90             // seeking at the middle
91             fch.position(32);
92             checkState(raf, fch, 32, 64);
93 
94             // truncating beyond offset
95             fch.truncate(42);
96             checkState(raf, fch, 32, 42);
97 
98             // truncating before offset
99             fch.truncate(16);
100             checkState(raf, fch, 16, 16);
101 
102             // writing at position beyond EOF
103             fch.write(ByteBuffer.wrap(new byte[1]), 127);
104             checkState(raf, fch, 16, 128);
105 
106             // writing at position before EOF
107             fch.write(ByteBuffer.wrap(new byte[1]), 42);
108             checkState(raf, fch, 16, 128);
109 
110             // truncating
111             raf.setLength(64);
112             checkState(raf, fch, 16, 64);
113 
114             // changing offset
115             raf.seek(21);
116             checkState(raf, fch, 21, 64);
117 
118             // skipping should change offset
119             raf.skipBytes(4);
120             checkState(raf, fch, 25, 64);
121 
122             // reading should change offset
123             raf.read();
124             checkState(raf, fch, 26, 64);
125 
126             // truncating to zero
127             raf.setLength(0);
128             checkState(raf, fch, 0, 0);
129 
130             // FileChannel cannot expand size
131             fch.truncate(42);
132             checkState(raf, fch, 0, 0);
133 
134             // expanding
135             raf.setLength(42);
136             checkState(raf, fch, 0, 42);
137 
138             // seeking beyond EOF
139             raf.seek(512);
140             checkState(raf, fch, 512, 42);
141 
142             // truncating to the same size
143             fch.truncate(256);
144             checkState(raf, fch, 256, 42);
145 
146             // truncating to the same size
147             fch.truncate(42);
148             checkState(raf, fch, 42, 42);
149 
150             // truncating to zero
151             fch.truncate(0);
152             checkState(raf, fch, 0, 0);
153         }
154     }
155 }
156