blob: e026f9f9d7e8e0e24ecc92a9afb45b1f93ef14b4 [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 java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLConnection;
import java.util.Arrays;
import junit.framework.Test;
import junit.framework.TestCase;
import org.apache.commons.AbstractVfsTestCase;
import org.apache.commons.vfs.Capability;
import org.apache.commons.vfs.FileContent;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystem;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.impl.DefaultFileSystemManager;
import org.apache.commons.vfs.provider.AbstractFileSystem;
import org.apache.commons.vfs.provider.local.DefaultLocalFileProvider;
/**
* File system test cases, which verifies the structure and naming
* functionality.
* <p/>
* Works from a base folder, and assumes a particular structure under
* that base folder.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
public abstract class AbstractProviderTestCase
extends AbstractVfsTestCase
{
private FileObject baseFolder;
private FileObject readFolder;
private FileObject writeFolder;
private DefaultFileSystemManager manager;
private ProviderTestConfig providerConfig;
private Method method;
private boolean addEmptyDir;
// Expected contents of "file1.txt"
public static final String FILE1_CONTENT = "This is a test file.";
// Expected contents of test files
public static final String TEST_FILE_CONTENT = "A test file.";
/**
* Sets the test method.
*/
public void setMethod(final Method method)
{
this.method = method;
}
/**
* Configures this test.
*/
public void setConfig(final DefaultFileSystemManager manager,
final ProviderTestConfig providerConfig,
final FileObject baseFolder,
final FileObject readFolder,
final FileObject writeFolder)
{
this.manager = manager;
this.providerConfig = providerConfig;
this.baseFolder = baseFolder;
this.readFolder = readFolder;
this.writeFolder = writeFolder;
}
/**
* Returns the file system manager used by this test.
*/
protected DefaultFileSystemManager getManager()
{
return manager;
}
/**
* creates a new uninitialized file system manager
* @throws Exception
*/
protected DefaultFileSystemManager createManager() throws Exception
{
DefaultFileSystemManager fs = getProviderConfig().getDefaultFileSystemManager();
fs.setFilesCache(getProviderConfig().getFilesCache());
getProviderConfig().prepare(fs);
if (!fs.hasProvider("file"))
{
fs.addProvider("file", new DefaultLocalFileProvider());
}
return fs;
}
/**
* some provider config do some post-initialization in getBaseTestFolder.
* This is a hack to allow access to this code for <code>createManager</code>
*/
public FileObject getBaseTestFolder(FileSystemManager fs) throws Exception
{
return providerConfig.getBaseTestFolder(fs);
}
/**
* Returns the base test folder. This is the parent of both the read
* test and write test folders.
*/
public FileObject getBaseFolder()
{
return baseFolder;
}
/**
* get the provider configuration
*/
public ProviderTestConfig getProviderConfig()
{
return providerConfig;
}
/**
* Returns the read test folder.
*/
protected FileObject getReadFolder()
{
return readFolder;
}
/**
* Returns the write test folder.
*/
protected FileObject getWriteFolder()
{
return writeFolder;
}
/**
* Sets the write test folder.
* @param folder
*/
protected void setWriteFolder(FileObject folder)
{
writeFolder = folder;
}
/**
* Returns the capabilities required by the tests of this test case. The
* tests are not run if the provider being tested does not support all
* the required capabilities. Return null or an empty array to always
* run the tests.
* <p/>
* <p>This implementation returns null.
*/
protected Capability[] getRequiredCaps()
{
return null;
}
/**
* Runs the test. This implementation short-circuits the test if the
* provider being tested does not have the capabilities required by this
* test.
*
* @todo Handle negative caps as well - ie, only run a test if the provider does not have certain caps.
* @todo Figure out how to remove the test from the TestResult if the test is skipped.
*/
protected void runTest() throws Throwable
{
// Check the capabilities
final Capability[] caps = getRequiredCaps();
if (caps != null)
{
for (int i = 0; i < caps.length; i++)
{
final Capability cap = caps[i];
FileSystem fs = readFolder.getFileSystem();
String name = fs.getClass().getName();
int index = name.lastIndexOf('.');
String fsName = (index > 0) ? name.substring(index + 1) : name;
if (!fs.hasCapability(cap))
{
System.out.println("skipping " + getName() + " because " +
fsName + " does not have capability " + cap);
return;
}
}
}
// Provider has all the capabilities - execute the test
if (method != null)
{
try
{
method.invoke(this, (Object[]) null);
}
catch (final InvocationTargetException e)
{
throw e.getTargetException();
}
}
else
{
super.runTest();
}
if (((AbstractFileSystem) readFolder.getFileSystem()).isOpen())
{
String name = "unknown";
if (method != null)
{
name = method.getName();
}
throw new IllegalStateException(getClass().getName() + ": filesystem has open streams after: " + name);
}
}
/**
* Asserts that the content of a file is the same as expected. Checks the
* length reported by getContentLength() is correct, then reads the content
* as a byte stream and compares the result with the expected content.
* Assumes files are encoded using UTF-8.
*/
protected void assertSameURLContent(final String expected,
final URLConnection connection)
throws Exception
{
// Get file content as a binary stream
final byte[] expectedBin = expected.getBytes("utf-8");
// Check lengths
assertEquals("same content length", expectedBin.length, connection.getContentLength());
// Read content into byte array
final InputStream instr = connection.getInputStream();
final ByteArrayOutputStream outstr;
try
{
outstr = new ByteArrayOutputStream();
final byte[] buffer = new byte[256];
int nread = 0;
while (nread >= 0)
{
outstr.write(buffer, 0, nread);
nread = instr.read(buffer);
}
}
finally
{
instr.close();
}
// Compare
assertTrue("same binary content", Arrays.equals(expectedBin, outstr.toByteArray()));
}
/**
* Asserts that the content of a file is the same as expected. Checks the
* length reported by getSize() is correct, then reads the content as
* a byte stream and compares the result with the expected content.
* Assumes files are encoded using UTF-8.
*/
protected void assertSameContent(final String expected,
final FileObject file)
throws Exception
{
// Check the file exists, and is a file
assertTrue(file.exists());
assertSame(FileType.FILE, file.getType());
// Get file content as a binary stream
final byte[] expectedBin = expected.getBytes("utf-8");
// Check lengths
final FileContent content = file.getContent();
assertEquals("same content length", expectedBin.length, content.getSize());
// Read content into byte array
final InputStream instr = content.getInputStream();
final ByteArrayOutputStream outstr;
try
{
outstr = new ByteArrayOutputStream(expectedBin.length);
final byte[] buffer = new byte[256];
int nread = 0;
while (nread >= 0)
{
outstr.write(buffer, 0, nread);
nread = instr.read(buffer);
}
}
finally
{
instr.close();
}
// Compare
assertTrue("same binary content", Arrays.equals(expectedBin, outstr.toByteArray()));
}
/**
* Builds the expected structure of the read tests folder.
*/
protected FileInfo buildExpectedStructure() throws FileSystemException
{
// Build the expected structure
final FileInfo base = new FileInfo(getReadFolder().getName().getBaseName(), FileType.FOLDER);
base.addFile("file1.txt", FILE1_CONTENT);
// file%.txt - test out encoding
base.addFile("file%25.txt", FILE1_CONTENT);
// file?test.txt - test out encoding (test.txt is not the queryString)
// as we do not know if the current file provider we need to
// ask it to normalize the name
// todo: move this into the FileInfo class to do it generally?
/* webdav-bug?: didnt manage to get the "?" correctly through webdavlib
FileSystemManager fsm = getReadFolder().getFileSystem().getFileSystemManager();
FileName fn = fsm.resolveName(getReadFolder().getName(), "file%3ftest.txt");
String baseName = fn.getBaseName();
base.addFile(baseName, FILE1_CONTENT);
*/
base.addFile("file space.txt", FILE1_CONTENT);
base.addFile("empty.txt", "");
if (addEmptyDir)
{
base.addFolder("emptydir");
}
final FileInfo dir = base.addFolder("dir1");
dir.addFile("file1.txt", TEST_FILE_CONTENT);
dir.addFile("file2.txt", TEST_FILE_CONTENT);
dir.addFile("file3.txt", TEST_FILE_CONTENT);
final FileInfo subdir1 = dir.addFolder("subdir1");
subdir1.addFile("file1.txt", TEST_FILE_CONTENT);
subdir1.addFile("file2.txt", TEST_FILE_CONTENT);
subdir1.addFile("file3.txt", TEST_FILE_CONTENT);
final FileInfo subdir2 = dir.addFolder("subdir2");
subdir2.addFile("file1.txt", TEST_FILE_CONTENT);
subdir2.addFile("file2.txt", TEST_FILE_CONTENT);
subdir2.addFile("file3.txt", TEST_FILE_CONTENT);
final FileInfo subdir3 = dir.addFolder("subdir3");
subdir3.addFile("file1.txt", TEST_FILE_CONTENT);
subdir3.addFile("file2.txt", TEST_FILE_CONTENT);
subdir3.addFile("file3.txt", TEST_FILE_CONTENT);
return base;
}
protected void addEmptyDir(boolean addEmptyDir)
{
this.addEmptyDir = addEmptyDir;
}
protected static Test notConfigured(Class testClass)
{
return warning(testClass + " is not configured for tests, skipping");
}
private static Test warning(final String message)
{
return new TestCase("warning")
{
protected void runTest()
{
System.out.println(message);
}
};
}
}