blob: de153f240dd57fabe01653908dd7e313a4e02e88 [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.vfs2.provider.ram;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.vfs2.AllFileSelector;
import org.apache.commons.vfs2.FileContent;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.FileType;
import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
import org.apache.commons.vfs2.provider.UriParser;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* Custom tests for RamProvider.
*/
public class CustomRamProviderTest {
/** List of URL special characters encoded for AbstractFileObject#getChild */
final char[] ENC = { /*'#',*/ '!', '?'};
private static final byte[] NON_EMPTY_FILE_CONTENT = new byte[] { 1, 2, 3 };
private final List<Closeable> closeables = new ArrayList<>();
FileSystemOptions defaultRamFso = new FileSystemOptions();
DefaultFileSystemManager manager;
FileSystemOptions smallSizedFso = new FileSystemOptions();
FileSystemOptions zeroSizedFso = new FileSystemOptions();
/**
* Closes the given {@link Closeable} during the tearDown phase.
*/
private <C extends Closeable> C closeOnTearDown(final C closeable) {
this.closeables.add(closeable);
return closeable;
}
private InputStream createEmptyFile() throws FileSystemException, IOException {
final FileObject root = manager.resolveFile("ram://file");
root.createFile();
return this.closeOnTearDown(root.getContent().getInputStream());
}
private InputStream createNonEmptyFile() throws FileSystemException, IOException {
final FileObject root = manager.resolveFile("ram://file");
root.createFile();
final FileContent content = root.getContent();
final OutputStream output = this.closeOnTearDown(content.getOutputStream());
output.write(1);
output.write(2);
output.write(3);
output.flush();
output.close();
return this.closeOnTearDown(content.getInputStream());
}
/** Create directory structure for {@link #testSpecialName()} and {@link #testSchemePrefix()} */
private FileObject prepareSpecialFile(final String dirname, final String testFileName) throws FileSystemException
{
// set up a folder containing an filename with special characters:
final FileObject dir = manager.resolveFile("ram:" + dirname);
dir.createFolder();
// construct the absolute name to make sure the relative name is not miss-interpreted
// ("./" + UriParser.encode(testFileName, ENC) would also work)
final String filePath = dir.getName().getPath() + "/" + UriParser.encode(testFileName, ENC);
final FileObject specialFile = dir.resolveFile(filePath);
specialFile.createFile();
return dir;
}
@Before
public void setUp() throws Exception {
manager = new DefaultFileSystemManager();
manager.addProvider("ram", new RamFileProvider());
manager.init();
// File Systems Options
RamFileSystemConfigBuilder.getInstance().setMaxSize(zeroSizedFso, 0L);
RamFileSystemConfigBuilder.getInstance().setMaxSize(smallSizedFso, 10L);
}
@After
public void tearDown() throws Exception {
for (final Closeable closeable : this.closeables) {
try {
closeable.close();
} catch (final Exception e) {
// ignore
}
}
manager.close();
}
@Test
public void testReadEmptyFileByteByByte() throws FileSystemException, IOException {
final InputStream input = this.createEmptyFile();
assertEquals("Empty file didnt return EOF -1", -1, input.read());
}
@Test
public void testReadEmptyFileIntoBuffer() throws FileSystemException, IOException {
final InputStream input = this.createEmptyFile();
final byte[] buffer = new byte[100];
assertEquals("Empty file didnt return when filling buffer", -1, input.read(buffer));
assertArrayEquals("Buffer was written too", new byte[100], buffer);
}
@Test
public void testReadEmptyFileIntoBufferWithOffsetAndLength() throws FileSystemException, IOException {
final InputStream input = this.createEmptyFile();
final byte[] buffer = new byte[100];
assertEquals("Empty file didnt return when filling buffer", -1, input.read(buffer, 10, 90));
assertArrayEquals("Buffer was written too", new byte[100], buffer);
}
@Test
public void testReadNonEmptyFileByteByByte() throws FileSystemException, IOException {
final InputStream input = this.createNonEmptyFile();
assertEquals("Read 1st byte failed", 1, input.read());
assertEquals("Rread 2st byte failed", 2, input.read());
assertEquals("Read 3st byte failed", 3, input.read());
assertEquals("File should be empty", -1, input.read());
}
@Test
public void testReadNonEmptyFileIntoBuffer() throws FileSystemException, IOException {
final InputStream input = this.createNonEmptyFile();
final byte[] buffer = new byte[100];
assertEquals("Filling buffer failed when file is not empty", NON_EMPTY_FILE_CONTENT.length, input.read(buffer));
final byte[] expectedBuffer = new byte[100];
System.arraycopy(NON_EMPTY_FILE_CONTENT, 0, expectedBuffer, 0, NON_EMPTY_FILE_CONTENT.length);
assertArrayEquals("Buffer not filled", expectedBuffer, buffer);
Arrays.fill(buffer, (byte) 0);
Arrays.fill(expectedBuffer, (byte) 0);
assertEquals("File should be empty after filling buffer", -1, input.read(buffer));
assertArrayEquals("Buffer was written when empty", expectedBuffer, buffer);
}
@Test
public void testReadNonEmptyFileIntoBufferWithOffsetAndLength() throws FileSystemException, IOException {
final InputStream input = this.createNonEmptyFile();
final byte[] buffer = new byte[100];
final int offset = 10;
assertEquals("Filling buffer failed when file is not empty", NON_EMPTY_FILE_CONTENT.length,
input.read(buffer, offset, 100 - offset));
final byte[] expectedBuffer = new byte[100];
System.arraycopy(NON_EMPTY_FILE_CONTENT, 0, expectedBuffer, offset, NON_EMPTY_FILE_CONTENT.length);
assertArrayEquals("Buffer not filled", expectedBuffer, buffer);
Arrays.fill(buffer, (byte) 0);
Arrays.fill(expectedBuffer, (byte) 0);
assertEquals("File should be empty after filling buffer", -1, input.read(buffer, 10, 90));
assertArrayEquals("Buffer was written when empty", expectedBuffer, buffer);
}
/**
*
* Checks root folder exists
*
* @throws FileSystemException
*/
@Test
public void testRootFolderExists() throws FileSystemException {
final FileObject root = manager.resolveFile("ram:///", defaultRamFso);
assertTrue(root.getType().hasChildren());
try {
root.delete();
fail();
} catch (final FileSystemException e) {
// Expected
}
}
@Test
public void testFSOptions() throws Exception {
// Default FS
final FileObject fo1 = manager.resolveFile("ram:/");
final FileObject fo2 = manager.resolveFile("ram:/");
assertSame("Both files should exist in the same fs instance.", fo1.getFileSystem(), fo2.getFileSystem());
FileSystemOptions fsOptions = fo1.getFileSystem().getFileSystemOptions();
long maxFilesystemSize = RamFileSystemConfigBuilder.getInstance().getLongMaxSize(fsOptions);
assertEquals("Filesystem option maxSize must be unlimited", Long.MAX_VALUE, maxFilesystemSize);
// Small FS
final FileObject fo3 = manager.resolveFile("ram:/fo3", smallSizedFso);
final FileObject fo4 = manager.resolveFile("ram:/", smallSizedFso);
assertSame("Both files should exist in the same FileSystem instance.", fo3.getFileSystem(), fo4.getFileSystem());
assertNotSame("Both files should exist in different FileSystem instance.", fo1.getFileSystem(), fo3.getFileSystem());
fsOptions = fo3.getFileSystem().getFileSystemOptions();
maxFilesystemSize = RamFileSystemConfigBuilder.getInstance().getLongMaxSize(fsOptions);
assertEquals("Filesystem option maxSize must be set", 10, maxFilesystemSize);
}
@Test
public void testSmallFS() throws Exception {
// Small FS
final FileObject fo3 = manager.resolveFile("ram:/fo3", smallSizedFso);
fo3.createFile();
try {
final OutputStream os = fo3.getContent().getOutputStream();
os.write(new byte[10]);
os.close();
} catch (final FileSystemException e) {
fail("Test should be able to save such a small file");
}
try {
final OutputStream os = fo3.getContent().getOutputStream();
os.write(new byte[11]);
os.close();
fail("It shouldn't save such a big file");
} catch (final FileSystemException e) {
// Expected
}
}
/**
* Tests VFS-625.
* @throws FileSystemException
*/
@Test
public void testMoveFile() throws FileSystemException {
final FileObject fileSource = manager.resolveFile("ram://virtual/source");
fileSource.createFile();
final FileObject fileDest = manager.resolveFile("ram://virtual/dest");
Assert.assertTrue(fileSource.canRenameTo(fileDest));
fileSource.moveTo(fileDest);
}
/**
* Test some special file name symbols.
* <p>
* Use the RamProvider since it has no character limitations like
* the (Windows) LocalFileProvider.
*/
@Test
public void testSpecialName() throws FileSystemException
{
// we test with this file name
// does not work with '!'
final String testDir = "/spacialtest/";
final String testFileName = "test:+-_ \"()<>%#.txt";
final String expectedName = testDir + testFileName;
final FileObject dir = prepareSpecialFile(testDir, testFileName);
// DO: verify you can list it:
final FileObject[] findFilesResult = dir.findFiles(new AllFileSelector()); // includes dir
final FileObject[] getChildrenResult = dir.getChildren();
final FileObject getChildResult = dir.getChild(UriParser.encode(testFileName, ENC));
// validate findFiles returns expected result
assertEquals("Unexpected result findFiles: " + Arrays.toString(findFilesResult), 2, findFilesResult.length);
String resultName = findFilesResult[0].getName().getPathDecoded();
assertEquals("findFiles Child name does not match", expectedName, resultName);
assertEquals("Did findFiles but child was no file", FileType.FILE, findFilesResult[0].getType());
// validate getChildren returns expected result
assertEquals("Unexpected result getChildren: " + Arrays.toString(getChildrenResult), 1, getChildrenResult.length);
resultName = getChildrenResult[0].getName().getPathDecoded();
assertEquals("getChildren Child name does not match", expectedName, resultName);
assertEquals("Did getChildren but child was no file", FileType.FILE, getChildrenResult[0].getType());
// validate getChild returns expected child
assertNotNull("Did not find direct child", getChildResult);
resultName = getChildResult.getName().getPathDecoded();
assertEquals("getChild name does not match", expectedName, resultName);
assertEquals("getChild was no file", FileType.FILE, getChildResult.getType());
}
/**
* Test if listing files with known scheme prefix works.
* <p>
* This test is not RamProvider specific but it uses it as a simple test-bed.
* Verifies VFS-741.
*/
@Test
public void testSchemePrefix() throws FileSystemException
{
// use a :-prefix with a known scheme (unknown scheme works since VFS-398)
final String KNOWN_SCHEME = manager.getSchemes()[0]; // typically "ram"
// we test with this file name
final String testDir = "/prefixtest/";
final String testFileName = KNOWN_SCHEME + ":test:txt";
final String expectedName = testDir + testFileName;
final FileObject dir = prepareSpecialFile(testDir, testFileName);
// verify we can list dir
// if not it throws:
// Caused by: org.apache.commons.vfs2.FileSystemException: Invalid descendent file name "ram:data:test.txt".
// at org.apache.commons.vfs2.impl.DefaultFileSystemManager.resolveName
// at org.apache.commons.vfs2.provider.AbstractFileObject.getChildren
// at org.apache.commons.vfs2.provider.AbstractFileObject.traverse
// at org.apache.commons.vfs2.provider.AbstractFileObject.findFiles
// test methods to get the child:
final FileObject[] findFilesResult = dir.findFiles(new AllFileSelector()); // includes dir
final FileObject[] getChildrenResult = dir.getChildren();
final FileObject getChildResult = dir.getChild(testFileName);
// validate findFiles returns expected result
assertEquals("Unexpected result findFiles: " + Arrays.toString(findFilesResult), 2, findFilesResult.length);
String resultName = findFilesResult[0].getName().getPathDecoded();
assertEquals("findFiles Child name does not match", expectedName, resultName);
assertEquals("Did findFiles but child was no file", FileType.FILE, findFilesResult[0].getType());
// validate getChildren returns expected result
assertEquals("Unexpected result getChildren: " + Arrays.toString(getChildrenResult), 1, getChildrenResult.length);
resultName = getChildrenResult[0].getName().getPathDecoded();
assertEquals("getChildren Child name does not match", expectedName, resultName);
assertEquals("Did getChildren but child was no file", FileType.FILE, getChildrenResult[0].getType());
// validate getChild returns expected child
assertNotNull("Did not find direct child", getChildResult);
resultName = getChildResult.getName().getPathDecoded();
assertEquals("getChild name does not match", expectedName, resultName);
assertEquals("getChild was no file", FileType.FILE, getChildResult.getType());
}
}