/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.harmony.tests.java.nio.channels;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.NonReadableChannelException;
import java.nio.channels.NonWritableChannelException;
import java.nio.channels.OverlappingFileLockException;
import junit.framework.TestCase;
/**
* API tests for the NIO FileChannel locking APIs
*/
public class FileChannelLockingTest extends TestCase {
private FileChannel readOnlyChannel;
private FileChannel writeOnlyChannel;
private FileChannel readWriteChannel;
private final String CONTENT = "The best things in life are nearest: Breath in your nostrils, light in your eyes, "
+ "flowers at your feet, duties at your hand, the path of right just before you. Then do not grasp at the stars, "
+ "but do life's plain, common work as it comes, certain that daily duties and daily bread are the sweetest "
+ " things in life.--Robert Louis Stevenson";
protected void setUp() throws Exception {
super.setUp();
// Create a three temporary files with content.
File[] tempFiles = new File[3];
for (int i = 0; i < tempFiles.length; i++) {
tempFiles[i] = File.createTempFile("testing", "tmp");
tempFiles[i].deleteOnExit();
FileWriter writer = new FileWriter(tempFiles[i]);
writer.write(CONTENT);
writer.close();
}
// Open read, write, and read/write channels on the temp files.
FileInputStream fileInputStream = new FileInputStream(tempFiles[0]);
readOnlyChannel = fileInputStream.getChannel();
FileOutputStream fileOutputStream = new FileOutputStream(tempFiles[1]);
writeOnlyChannel = fileOutputStream.getChannel();
RandomAccessFile randomAccessFile = new RandomAccessFile(tempFiles[2],
"rw");
readWriteChannel = randomAccessFile.getChannel();
}
protected void tearDown() throws IOException {
if (readOnlyChannel != null) {
readOnlyChannel.close();
}
if (writeOnlyChannel != null) {
writeOnlyChannel.close();
}
if (readWriteChannel != null) {
readWriteChannel.close();
}
}
public void test_illegalLocks() throws IOException {
// Cannot acquire an exclusive lock on a read-only file channel
try {
readOnlyChannel.lock();
fail("Acquiring a full exclusive lock on a read only channel should fail.");
} catch (NonWritableChannelException ex) {
// Expected.
}
// Cannot get a shared lock on a write-only file channel.
try {
writeOnlyChannel.lock(1, 10, true);
fail("Acquiring a shared lock on a write-only channel should fail.");
} catch (NonReadableChannelException ex) {
// expected
}
}
public void test_lockReadWrite() throws IOException {
// Acquire an exclusive lock across the entire file.
FileLock flock = readWriteChannel.lock();
if (flock != null) {
flock.release();
}
}
public void test_illegalLockParameters() throws IOException {
// Cannot lock negative positions
try {
readOnlyChannel.lock(-1, 10, true);
fail("Passing illegal args to lock should fail.");
} catch (IllegalArgumentException ex) {
// expected
}
try {
writeOnlyChannel.lock(-1, 10, false);
fail("Passing illegal args to lock should fail.");
} catch (IllegalArgumentException ex) {
// expected
}
try {
readWriteChannel.lock(-1, 10, false);
fail("Passing illegal args to lock should fail.");
} catch (IllegalArgumentException ex) {
// expected
}
// Lock a range at the front, shared.
FileLock flock1 = readWriteChannel.lock(22, 110, true);
// Try to acquire an overlapping lock.
try {
readWriteChannel.lock(75, 210, true);
} catch (OverlappingFileLockException exception) {
// expected
flock1.release();
}
}
public void test_lockLLZ() throws IOException {
// Lock a range at the front, non-shared.
FileLock flock1 = readWriteChannel.lock(0, 10, false);
// Lock a shared range further in the same file.
FileLock flock2 = readWriteChannel.lock(22, 100, true);
// The spec allows the impl to refuse shared locks
flock1.release();
flock2.release();
}
public void test_tryLock() throws IOException {
try {
readOnlyChannel.tryLock();
fail("Acquiring a full exclusive lock on a read channel should have thrown an exception.");
} catch (NonWritableChannelException ex) {
// Expected.
}
}
public void test_tryLockLLZ() throws IOException {
// It is illegal to request an exclusive lock on a read-only channel
try {
readOnlyChannel.tryLock(0, 99, false);
fail("Acquiring exclusive lock on read-only channel should fail");
} catch (NonWritableChannelException ex) {
// Expected
}
// It is invalid to request a lock starting before the file start
try {
readOnlyChannel.tryLock(-99, 0, true);
fail("Acquiring an illegal lock value should fail.");
} catch (IllegalArgumentException ex) {
// expected
}
// Acquire a valid lock
FileLock tmpLock = readOnlyChannel.tryLock(0, 10, true);
assertTrue(tmpLock.isValid());
tmpLock.release();
// Acquire another valid lock -- and don't release it yet
FileLock lock = readOnlyChannel.tryLock(10, 788, true);
assertTrue(lock.isValid());
// Overlapping locks are illegal
try {
readOnlyChannel.tryLock(1, 23, true);
fail("Acquiring an overlapping lock should fail.");
} catch (OverlappingFileLockException ex) {
// Expected
}
// Adjacent locks are legal
FileLock adjacentLock = readOnlyChannel.tryLock(1, 3, true);
assertTrue(adjacentLock.isValid());
adjacentLock.release();
// Release longer lived lock
lock.release();
}
}