blob: 8212734e8025e86436c4c6cc96e92ed0f361279b [file] [log] [blame]
/*
* 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.commons.vfs.test;
import org.apache.commons.vfs.Capability;
import org.apache.commons.vfs.FileChangeEvent;
import org.apache.commons.vfs.FileListener;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystem;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.Selectors;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
/**
* File system test that check that a file system can be modified.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
*/
public class ProviderWriteTests
extends AbstractProviderTestCase
{
/**
* Returns the capabilities required by the tests of this test case.
*/
protected Capability[] getRequiredCaps()
{
return new Capability[]
{
Capability.CREATE,
Capability.DELETE,
Capability.GET_TYPE,
Capability.LIST_CHILDREN,
Capability.READ_CONTENT,
Capability.WRITE_CONTENT
};
}
/**
* Sets up a scratch folder for the test to use.
*/
protected FileObject createScratchFolder() throws Exception
{
FileObject scratchFolder = getWriteFolder();
// Make sure the test folder is empty
scratchFolder.delete(Selectors.EXCLUDE_SELF);
scratchFolder.createFolder();
return scratchFolder;
}
/**
* Tests folder creation.
*/
public void testFolderCreate() throws Exception
{
FileObject scratchFolder = createScratchFolder();
// Create direct child of the test folder
FileObject folder = scratchFolder.resolveFile("dir1");
assertTrue(!folder.exists());
folder.createFolder();
assertTrue(folder.exists());
assertSame(FileType.FOLDER, folder.getType());
assertEquals(0, folder.getChildren().length);
// Create a descendant, where the intermediate folders don't exist
folder = scratchFolder.resolveFile("dir2/dir1/dir1");
assertTrue(!folder.exists());
assertTrue(!folder.getParent().exists());
assertTrue(!folder.getParent().getParent().exists());
folder.createFolder();
assertTrue(folder.exists());
assertSame(FileType.FOLDER, folder.getType());
assertEquals(0, folder.getChildren().length);
assertTrue(folder.getParent().exists());
assertTrue(folder.getParent().getParent().exists());
// Test creating a folder that already exists
assertTrue(folder.exists());
folder.createFolder();
}
/**
* Tests file creation
*/
public void testFileCreate() throws Exception
{
FileObject scratchFolder = createScratchFolder();
// Create direct child of the test folder
FileObject file = scratchFolder.resolveFile("file1.txt");
assertTrue(!file.exists());
file.createFile();
assertTrue(file.exists());
assertSame(FileType.FILE, file.getType());
assertEquals(0, file.getContent().getSize());
assertFalse(file.isHidden());
assertTrue(file.isReadable());
assertTrue(file.isWriteable());
// Create direct child of the test folder - special name
file = scratchFolder.resolveFile("file1%25.txt");
assertTrue(!file.exists());
file.createFile();
assertTrue(file.exists());
assertSame(FileType.FILE, file.getType());
assertEquals(0, file.getContent().getSize());
assertFalse(file.isHidden());
assertTrue(file.isReadable());
assertTrue(file.isWriteable());
// Create a descendant, where the intermediate folders don't exist
file = scratchFolder.resolveFile("dir1/dir1/file1.txt");
assertTrue(!file.exists());
assertTrue(!file.getParent().exists());
assertTrue(!file.getParent().getParent().exists());
file.createFile();
assertTrue(file.exists());
assertSame(FileType.FILE, file.getType());
assertEquals(0, file.getContent().getSize());
assertTrue(file.getParent().exists());
assertTrue(file.getParent().getParent().exists());
assertFalse(file.getParent().isHidden());
assertFalse(file.getParent().getParent().isHidden());
// Test creating a file that already exists
assertTrue(file.exists());
file.createFile();
assertTrue(file.exists());
assertTrue(file.isReadable());
assertTrue(file.isWriteable());
}
/**
* Tests file/folder creation with mismatched types.
*/
public void testFileCreateMismatched() throws Exception
{
FileObject scratchFolder = createScratchFolder();
// Create a test file and folder
FileObject file = scratchFolder.resolveFile("dir1/file1.txt");
file.createFile();
assertEquals(FileType.FILE, file.getType());
FileObject folder = scratchFolder.resolveFile("dir1/dir2");
folder.createFolder();
assertEquals(FileType.FOLDER, folder.getType());
// Attempt to create a file that already exists as a folder
try
{
folder.createFile();
fail();
}
catch (FileSystemException exc)
{
}
// Attempt to create a folder that already exists as a file
try
{
file.createFolder();
fail();
}
catch (FileSystemException exc)
{
}
// Attempt to create a folder as a child of a file
FileObject folder2 = file.resolveFile("some-child");
try
{
folder2.createFolder();
fail();
}
catch (FileSystemException exc)
{
}
}
/**
* Tests deletion
*/
public void testDelete() throws Exception
{
// Set-up the test structure
FileObject folder = createScratchFolder();
folder.resolveFile("file1.txt").createFile();
folder.resolveFile("file%25.txt").createFile();
folder.resolveFile("emptydir").createFolder();
folder.resolveFile("dir1/file1.txt").createFile();
folder.resolveFile("dir1/dir2/file2.txt").createFile();
// Delete a file
FileObject file = folder.resolveFile("file1.txt");
assertTrue(file.exists());
file.delete(Selectors.SELECT_ALL);
assertTrue(!file.exists());
// Delete a special name file
file = folder.resolveFile("file%25.txt");
assertTrue(file.exists());
file.delete(Selectors.SELECT_ALL);
assertTrue(!file.exists());
// Delete an empty folder
file = folder.resolveFile("emptydir");
assertTrue(file.exists());
file.delete(Selectors.SELECT_ALL);
assertTrue(!file.exists());
// Recursive delete
file = folder.resolveFile("dir1");
FileObject file2 = file.resolveFile("dir2/file2.txt");
assertTrue(file.exists());
assertTrue(file2.exists());
file.delete(Selectors.SELECT_ALL);
assertTrue(!file.exists());
assertTrue(!file2.exists());
// Delete a file that does not exist
file = folder.resolveFile("some-folder/some-file");
assertTrue(!file.exists());
file.delete(Selectors.SELECT_ALL);
assertTrue(!file.exists());
}
/**
* Tests concurrent read and write on the same file fails.
*/
/* imario@apache.org leave this to some sort of LockManager
public void testConcurrentReadWrite() throws Exception
{
final FileObject scratchFolder = createScratchFolder();
final FileObject file = scratchFolder.resolveFile("file1.txt");
file.createFile();
// Start reading from the file
final InputStream instr = file.getContent().getInputStream();
try
{
// Try to write to the file
file.getContent().getOutputStream();
fail();
}
catch (final FileSystemException e)
{
// Check error message
assertSameMessage("vfs.provider/write-in-use.error", file, e);
}
finally
{
instr.close();
}
}
*/
/**
* Tests concurrent writes on the same file fails.
*/
/* imario@apache.org leave this to some sort of LockManager
public void testConcurrentWrite() throws Exception
{
final FileObject scratchFolder = createScratchFolder();
final FileObject file = scratchFolder.resolveFile("file1.txt");
file.createFile();
// Start writing to the file
final OutputStream outstr = file.getContent().getOutputStream();
final String testContent = "some content";
try
{
// Write some content to the first stream
outstr.write(testContent.getBytes());
// Try to open another output stream
file.getContent().getOutputStream();
fail();
}
catch (final FileSystemException e)
{
// Check error message
assertSameMessage("vfs.provider/write-in-use.error", file, e);
}
finally
{
outstr.close();
}
// Make sure that the content written to the first stream is actually applied
assertSameContent(testContent, file);
}
*/
/**
* Tests file copy to and from the same filesystem type. This was a problem
* w/ FTP.
*/
public void testCopySameFileSystem() throws Exception
{
final FileObject scratchFolder = createScratchFolder();
// Create direct child of the test folder
final FileObject file = scratchFolder.resolveFile("file1.txt");
assertTrue(!file.exists());
// Create the source file
final String content = "Here is some sample content for the file. Blah Blah Blah.";
final OutputStream os = file.getContent().getOutputStream();
try
{
os.write(content.getBytes("utf-8"));
}
finally
{
os.close();
}
assertSameContent(content, file);
// Make sure we can copy the new file to another file on the same filesystem
FileObject fileCopy = scratchFolder.resolveFile("file1copy.txt");
assertTrue(!fileCopy.exists());
fileCopy.copyFrom(file, Selectors.SELECT_SELF);
assertSameContent(content, fileCopy);
}
/**
* Tests overwriting a file on the same file system.
*/
public void testOverwriteSameFileSystem() throws Exception
{
final FileObject scratchFolder = createScratchFolder();
// Create direct child of the test folder
final FileObject file = scratchFolder.resolveFile("file1.txt");
assertTrue(!file.exists());
// Create the source file
final String content = "Here is some sample content for the file. Blah Blah Blah.";
final OutputStream os = file.getContent().getOutputStream();
try
{
os.write(content.getBytes("utf-8"));
}
finally
{
os.close();
}
assertSameContent(content, file);
// Make sure we can copy the new file to another file on the same filesystem
FileObject fileCopy = scratchFolder.resolveFile("file1copy.txt");
assertTrue(!fileCopy.exists());
fileCopy.copyFrom(file, Selectors.SELECT_SELF);
assertSameContent(content, fileCopy);
// Make sure we can copy the same new file to the same target file on the same filesystem
assertTrue(fileCopy.exists());
fileCopy.copyFrom(file, Selectors.SELECT_SELF);
assertSameContent(content, fileCopy);
}
/**
* Tests create-delete-create-a-file sequence on the same file system.
*/
public void testCreateDeleteCreateSameFileSystem() throws Exception
{
final FileObject scratchFolder = createScratchFolder();
// Create direct child of the test folder
final FileObject file = scratchFolder.resolveFile("file1.txt");
assertTrue(!file.exists());
// Create the source file
final String content = "Here is some sample content for the file. Blah Blah Blah.";
final OutputStream os = file.getContent().getOutputStream();
try
{
os.write(content.getBytes("utf-8"));
}
finally
{
os.close();
}
assertSameContent(content, file);
// Make sure we can copy the new file to another file on the same filesystem
FileObject fileCopy = scratchFolder.resolveFile("file1copy.txt");
assertTrue(!fileCopy.exists());
fileCopy.copyFrom(file, Selectors.SELECT_SELF);
assertSameContent(content, fileCopy);
// Delete the file.
assertTrue(fileCopy.exists());
assertTrue(fileCopy.delete());
// Make sure we can copy the same new file to the same target file on the same filesystem
assertTrue(!fileCopy.exists());
fileCopy.copyFrom(file, Selectors.SELECT_SELF);
assertSameContent(content, fileCopy);
}
/**
* Test that children are handled correctly by create and delete.
*/
public void testListChildren() throws Exception
{
FileObject folder = createScratchFolder();
HashSet names = new HashSet();
// Make sure the folder is empty
assertEquals(0, folder.getChildren().length);
// Create a child folder
folder.resolveFile("dir1").createFolder();
names.add("dir1");
assertSameFileSet(names, folder.getChildren());
// Create a child file
folder.resolveFile("file1.html").createFile();
names.add("file1.html");
assertSameFileSet(names, folder.getChildren());
// Create a descendent
folder.resolveFile("dir2/file1.txt").createFile();
names.add("dir2");
assertSameFileSet(names, folder.getChildren());
// Create a child file via an output stream
OutputStream outstr = folder.resolveFile("file2.txt").getContent().getOutputStream();
outstr.close();
names.add("file2.txt");
assertSameFileSet(names, folder.getChildren());
// Delete a child folder
folder.resolveFile("dir1").delete(Selectors.SELECT_ALL);
names.remove("dir1");
assertSameFileSet(names, folder.getChildren());
// Delete a child file
folder.resolveFile("file1.html").delete(Selectors.SELECT_ALL);
names.remove("file1.html");
assertSameFileSet(names, folder.getChildren());
// Recreate the folder
folder.delete(Selectors.SELECT_ALL);
folder.createFolder();
assertEquals(0, folder.getChildren().length);
}
/**
* Check listeners are notified of changes.
*/
public void testListener() throws Exception
{
final FileObject baseFile = createScratchFolder();
FileObject child = baseFile.resolveFile("newfile.txt");
assertTrue(!child.exists());
FileSystem fs = baseFile.getFileSystem();
TestListener listener = new TestListener(child);
fs.addListener(child, listener);
// Create as a folder
listener.addCreateEvent();
child.createFolder();
listener.assertFinished();
// Create the folder again. Should not get an event.
child.createFolder();
// Delete
listener.addDeleteEvent();
child.delete();
listener.assertFinished();
// Delete again. Should not get an event
child.delete();
// Create as a file
listener.addCreateEvent();
child.createFile();
listener.assertFinished();
// Create the file again. Should not get an event
child.createFile();
listener.addDeleteEvent();
child.delete();
// Create as a file, by writing to it.
listener.addCreateEvent();
child.getContent().getOutputStream().close();
listener.assertFinished();
// Recreate the file by writing to it
child.getContent().getOutputStream().close();
// Copy another file over the top
final FileObject otherChild = baseFile.resolveFile("folder1");
otherChild.createFolder();
listener.addDeleteEvent();
listener.addCreateEvent();
child.copyFrom(otherChild, Selectors.SELECT_SELF);
listener.assertFinished();
fs.removeListener(child, listener);
}
/**
* Ensures the names of a set of files match an expected set.
*/
private void assertSameFileSet(Set names, FileObject[] files)
{
// Make sure the sets are the same length
assertEquals(names.size(), files.length);
// Check for unexpected names
for (int i = 0; i < files.length; i++)
{
FileObject file = files[i];
assertTrue(names.contains(file.getName().getBaseName()));
}
}
/**
* A test listener.
*/
private static class TestListener implements FileListener
{
private final FileObject file;
private final ArrayList events = new ArrayList();
private static final Object CREATE = "create";
private static final Object DELETE = "delete";
private static final Object CHANGED = "changed";
public TestListener(final FileObject file)
{
this.file = file;
}
/**
* Called when a file is created.
*/
public void fileCreated(final FileChangeEvent event)
{
assertTrue("Unexpected create event", events.size() > 0);
assertSame("Expecting a create event", CREATE, events.remove(0));
assertSame(file, event.getFile());
try
{
assertTrue(file.exists());
}
catch (FileSystemException e)
{
fail();
}
}
/**
* Called when a file is deleted.
*/
public void fileDeleted(final FileChangeEvent event)
{
assertTrue("Unexpected delete event", events.size() > 0);
assertSame("Expecting a delete event", DELETE, events.remove(0));
assertSame(file, event.getFile());
try
{
assertTrue(!file.exists());
}
catch (FileSystemException e)
{
fail();
}
}
public void fileChanged(FileChangeEvent event) throws Exception
{
assertTrue("Unexpected changed event", events.size() > 0);
assertSame("Expecting a changed event", CHANGED, events.remove(0));
assertSame(file, event.getFile());
try
{
assertTrue(!file.exists());
}
catch (FileSystemException e)
{
fail();
}
}
public void addCreateEvent()
{
events.add(CREATE);
}
public void addDeleteEvent()
{
events.add(DELETE);
}
public void assertFinished()
{
assertEquals("Missing event", 0, events.size());
}
}
}