1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.apache.harmony.tests.java.nio.channels;
18 
19 import java.io.File;
20 import java.io.FileInputStream;
21 import java.io.FileOutputStream;
22 import java.io.FileWriter;
23 import java.io.IOException;
24 import java.io.RandomAccessFile;
25 import java.nio.channels.FileChannel;
26 import java.nio.channels.FileLock;
27 import java.nio.channels.NonReadableChannelException;
28 import java.nio.channels.NonWritableChannelException;
29 import java.nio.channels.OverlappingFileLockException;
30 
31 import junit.framework.TestCase;
32 
33 /**
34  * API tests for the NIO FileChannel locking APIs
35  */
36 public class FileChannelLockingTest extends TestCase {
37 
38     private FileChannel readOnlyChannel;
39 
40     private FileChannel writeOnlyChannel;
41 
42     private FileChannel readWriteChannel;
43 
44     private final String CONTENT = "The best things in life are nearest: Breath in your nostrils, light in your eyes, "
45             + "flowers at your feet, duties at your hand, the path of right just before you. Then do not grasp at the stars, "
46             + "but do life's plain, common work as it comes, certain that daily duties and daily bread are the sweetest "
47             + " things in life.--Robert Louis Stevenson";
48 
setUp()49     protected void setUp() throws Exception {
50         super.setUp();
51 
52         // Create a three temporary files with content.
53         File[] tempFiles = new File[3];
54         for (int i = 0; i < tempFiles.length; i++) {
55             tempFiles[i] = File.createTempFile("testing", "tmp");
56             tempFiles[i].deleteOnExit();
57             FileWriter writer = new FileWriter(tempFiles[i]);
58             writer.write(CONTENT);
59             writer.close();
60         }
61 
62         // Open read, write, and read/write channels on the temp files.
63         FileInputStream fileInputStream = new FileInputStream(tempFiles[0]);
64         readOnlyChannel = fileInputStream.getChannel();
65 
66         FileOutputStream fileOutputStream = new FileOutputStream(tempFiles[1]);
67         writeOnlyChannel = fileOutputStream.getChannel();
68 
69         RandomAccessFile randomAccessFile = new RandomAccessFile(tempFiles[2],
70                 "rw");
71         readWriteChannel = randomAccessFile.getChannel();
72     }
73 
tearDown()74     protected void tearDown() throws IOException {
75         if (readOnlyChannel != null) {
76             readOnlyChannel.close();
77         }
78         if (writeOnlyChannel != null) {
79             writeOnlyChannel.close();
80         }
81         if (readWriteChannel != null) {
82             readWriteChannel.close();
83         }
84     }
85 
test_illegalLocks()86     public void test_illegalLocks() throws IOException {
87         // Cannot acquire an exclusive lock on a read-only file channel
88         try {
89             readOnlyChannel.lock();
90             fail("Acquiring a full exclusive lock on a read only channel should fail.");
91         } catch (NonWritableChannelException ex) {
92             // Expected.
93         }
94 
95         // Cannot get a shared lock on a write-only file channel.
96         try {
97             writeOnlyChannel.lock(1, 10, true);
98             fail("Acquiring a shared lock on a write-only channel should fail.");
99         } catch (NonReadableChannelException ex) {
100             // expected
101         }
102     }
103 
test_lockReadWrite()104     public void test_lockReadWrite() throws IOException {
105         // Acquire an exclusive lock across the entire file.
106         FileLock flock = readWriteChannel.lock();
107         if (flock != null) {
108             flock.release();
109         }
110     }
111 
test_illegalLockParameters()112     public void test_illegalLockParameters() throws IOException {
113         // Cannot lock negative positions
114         try {
115             readOnlyChannel.lock(-1, 10, true);
116             fail("Passing illegal args to lock should fail.");
117         } catch (IllegalArgumentException ex) {
118             // expected
119         }
120         try {
121             writeOnlyChannel.lock(-1, 10, false);
122             fail("Passing illegal args to lock should fail.");
123         } catch (IllegalArgumentException ex) {
124             // expected
125         }
126         try {
127             readWriteChannel.lock(-1, 10, false);
128             fail("Passing illegal args to lock should fail.");
129         } catch (IllegalArgumentException ex) {
130             // expected
131         }
132 
133         // Lock a range at the front, shared.
134         FileLock flock1 = readWriteChannel.lock(22, 110, true);
135 
136         // Try to acquire an overlapping lock.
137         try {
138             readWriteChannel.lock(75, 210, true);
139         } catch (OverlappingFileLockException exception) {
140             // expected
141             flock1.release();
142         }
143     }
144 
test_lockLLZ()145     public void test_lockLLZ() throws IOException {
146         // Lock a range at the front, non-shared.
147         FileLock flock1 = readWriteChannel.lock(0, 10, false);
148 
149         // Lock a shared range further in the same file.
150         FileLock flock2 = readWriteChannel.lock(22, 100, true);
151 
152         // The spec allows the impl to refuse shared locks
153         flock1.release();
154         flock2.release();
155     }
156 
test_tryLock()157     public void test_tryLock() throws IOException {
158         try {
159             readOnlyChannel.tryLock();
160             fail("Acquiring a full exclusive lock on a read channel should have thrown an exception.");
161         } catch (NonWritableChannelException ex) {
162             // Expected.
163         }
164     }
165 
test_tryLockLLZ()166     public void test_tryLockLLZ() throws IOException {
167         // It is illegal to request an exclusive lock on a read-only channel
168         try {
169             readOnlyChannel.tryLock(0, 99, false);
170             fail("Acquiring exclusive lock on read-only channel should fail");
171         } catch (NonWritableChannelException ex) {
172             // Expected
173         }
174 
175         // It is invalid to request a lock starting before the file start
176         try {
177             readOnlyChannel.tryLock(-99, 0, true);
178             fail("Acquiring an illegal lock value should fail.");
179         } catch (IllegalArgumentException ex) {
180             // expected
181         }
182 
183         // Acquire a valid lock
184         FileLock tmpLock = readOnlyChannel.tryLock(0, 10, true);
185         assertTrue(tmpLock.isValid());
186         tmpLock.release();
187 
188         // Acquire another valid lock -- and don't release it yet
189         FileLock lock = readOnlyChannel.tryLock(10, 788, true);
190         assertTrue(lock.isValid());
191 
192         // Overlapping locks are illegal
193         try {
194             readOnlyChannel.tryLock(1, 23, true);
195             fail("Acquiring an overlapping lock should fail.");
196         } catch (OverlappingFileLockException ex) {
197             // Expected
198         }
199 
200         // Adjacent locks are legal
201         FileLock adjacentLock = readOnlyChannel.tryLock(1, 3, true);
202         assertTrue(adjacentLock.isValid());
203         adjacentLock.release();
204 
205         // Release longer lived lock
206         lock.release();
207     }
208 }
209