/* * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0 * (the "License"). You may not use this work except in compliance with the License, which is * available at www.apache.org/licenses/LICENSE-2.0 * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied, as more fully set forth in the License. * * See the NOTICE file distributed with this work for information regarding copyright ownership. */ package alluxio.client; import static org.junit.Assert.assertFalse; import alluxio.AlluxioURI; import alluxio.Configuration; import alluxio.LocalAlluxioClusterResource; import alluxio.PropertyKey; import alluxio.BaseIntegrationTest; import alluxio.client.file.FileSystem; import alluxio.client.file.FileSystemTestUtils; import alluxio.client.file.URIStatus; import alluxio.client.file.options.CreateFileOptions; import alluxio.client.file.options.DeleteOptions; import alluxio.exception.AlluxioException; import alluxio.exception.DirectoryNotEmptyException; import alluxio.exception.FileAlreadyExistsException; import alluxio.exception.FileDoesNotExistException; import alluxio.exception.InvalidPathException; import alluxio.master.LocalAlluxioCluster; import alluxio.underfs.UnderFileSystem; import alluxio.util.UnderFileSystemUtils; import alluxio.util.io.PathUtils; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import java.io.IOException; /** * Integration tests on Alluxio Client (reuse the {@link LocalAlluxioCluster}). */ public final class FileSystemIntegrationTest extends BaseIntegrationTest { private static final int USER_QUOTA_UNIT_BYTES = 1000; @Rule public LocalAlluxioClusterResource mLocalAlluxioClusterResource = new LocalAlluxioClusterResource.Builder() .setProperty(PropertyKey.USER_FILE_BUFFER_BYTES, USER_QUOTA_UNIT_BYTES) .build(); private FileSystem mFileSystem = null; private CreateFileOptions mWriteBoth; private UnderFileSystem mUfs; @Rule public ExpectedException mThrown = ExpectedException.none(); @Before public void before() throws Exception { mFileSystem = mLocalAlluxioClusterResource.get().getClient(); mWriteBoth = CreateFileOptions.defaults().setWriteType(WriteType.CACHE_THROUGH); mUfs = UnderFileSystem.Factory.createForRoot(); } @Test public void getRoot() throws Exception { Assert.assertEquals(0, mFileSystem.getStatus(new AlluxioURI("/")).getFileId()); } @Test public void createFile() throws Exception { String uniqPath = PathUtils.uniqPath(); for (int k = 1; k < 5; k++) { AlluxioURI uri = new AlluxioURI(uniqPath + k); mFileSystem.createFile(uri, mWriteBoth).close(); Assert.assertNotNull(mFileSystem.getStatus(uri)); } } @Test public void deleteFile() throws Exception { String uniqPath = PathUtils.uniqPath(); for (int k = 0; k < 5; k++) { AlluxioURI fileURI = new AlluxioURI(uniqPath + k); FileSystemTestUtils.createByteFile(mFileSystem, fileURI.getPath(), k, mWriteBoth); Assert.assertTrue(mFileSystem.getStatus(fileURI).getInMemoryPercentage() == 100); Assert.assertNotNull(mFileSystem.getStatus(fileURI)); } for (int k = 0; k < 5; k++) { AlluxioURI fileURI = new AlluxioURI(uniqPath + k); mFileSystem.delete(fileURI); Assert.assertFalse(mFileSystem.exists(fileURI)); mThrown.expect(FileDoesNotExistException.class); mFileSystem.getStatus(fileURI); } } @Test public void getFileStatus() throws Exception { String uniqPath = PathUtils.uniqPath(); int writeBytes = USER_QUOTA_UNIT_BYTES * 2; AlluxioURI uri = new AlluxioURI(uniqPath); FileSystemTestUtils.createByteFile(mFileSystem, uri.getPath(), writeBytes, mWriteBoth); Assert.assertTrue(mFileSystem.getStatus(uri).getInMemoryPercentage() == 100); Assert.assertTrue(mFileSystem.getStatus(uri).getPath().equals(uniqPath)); } @Test public void renameFileTest1() throws Exception { String uniqPath = PathUtils.uniqPath(); AlluxioURI path1 = new AlluxioURI(uniqPath + 1); mFileSystem.createFile(path1, mWriteBoth).close(); for (int k = 1; k < 10; k++) { AlluxioURI fileA = new AlluxioURI(uniqPath + k); AlluxioURI fileB = new AlluxioURI(uniqPath + (k + 1)); URIStatus existingFile = mFileSystem.getStatus(fileA); long oldFileId = existingFile.getFileId(); Assert.assertNotNull(existingFile); mFileSystem.rename(fileA, fileB); URIStatus renamedFile = mFileSystem.getStatus(fileB); Assert.assertNotNull(renamedFile); Assert.assertEquals(oldFileId, renamedFile.getFileId()); } } @Test public void renameFileTest2() throws Exception { AlluxioURI uniqUri = new AlluxioURI(PathUtils.uniqPath()); mFileSystem.createFile(uniqUri, mWriteBoth).close(); URIStatus f = mFileSystem.getStatus(uniqUri); long oldFileId = f.getFileId(); mFileSystem.rename(uniqUri, uniqUri); Assert.assertEquals(oldFileId, mFileSystem.getStatus(uniqUri).getFileId()); } /** * Creates another directory on the local filesystem, alongside the existing Ufs, to be used as a * second Ufs. * * @return the path of the alternate Ufs directory */ private String createAlternateUfs() throws Exception { AlluxioURI parentURI = new AlluxioURI(Configuration.get(PropertyKey.MASTER_MOUNT_TABLE_ROOT_UFS)).getParent(); String alternateUfsRoot = parentURI.join("alternateUnderFSStorage").toString(); UnderFileSystemUtils.mkdirIfNotExists(mUfs, alternateUfsRoot); return alternateUfsRoot; } /** * Deletes the alternate under file system directory. * * @param alternateUfsRoot the root of the alternate Ufs */ private void destroyAlternateUfs(String alternateUfsRoot) throws Exception { UnderFileSystemUtils.deleteDirIfExists(mUfs, alternateUfsRoot); } @Test public void mountAlternateUfs() throws Exception { String alternateUfsRoot = createAlternateUfs(); try { String filePath = PathUtils.concatPath(alternateUfsRoot, "file1"); UnderFileSystemUtils.touch(mUfs, filePath); mFileSystem.mount(new AlluxioURI("/d1"), new AlluxioURI(alternateUfsRoot)); mFileSystem.loadMetadata(new AlluxioURI("/d1/file1")); Assert.assertEquals("file1", mFileSystem.listStatus(new AlluxioURI("/d1")).get(0).getName()); } finally { destroyAlternateUfs(alternateUfsRoot); } } @Test public void mountAlternateUfsSubdirs() throws Exception { String alternateUfsRoot = createAlternateUfs(); try { String dirPath1 = PathUtils.concatPath(alternateUfsRoot, "dir1"); String dirPath2 = PathUtils.concatPath(alternateUfsRoot, "dir2"); UnderFileSystemUtils.mkdirIfNotExists(mUfs, dirPath1); UnderFileSystemUtils.mkdirIfNotExists(mUfs, dirPath2); String filePath1 = PathUtils.concatPath(dirPath1, "file1"); String filePath2 = PathUtils.concatPath(dirPath2, "file2"); UnderFileSystemUtils.touch(mUfs, filePath1); UnderFileSystemUtils.touch(mUfs, filePath2); mFileSystem.mount(new AlluxioURI("/d1"), new AlluxioURI(dirPath1)); mFileSystem.mount(new AlluxioURI("/d2"), new AlluxioURI(dirPath2)); mFileSystem.loadMetadata(new AlluxioURI("/d1/file1")); mFileSystem.loadMetadata(new AlluxioURI("/d2/file2")); Assert.assertEquals("file1", mFileSystem.listStatus(new AlluxioURI("/d1")).get(0).getName()); Assert.assertEquals("file2", mFileSystem.listStatus(new AlluxioURI("/d2")).get(0).getName()); } finally { destroyAlternateUfs(alternateUfsRoot); } } @Test public void mountPrefixUfs() throws Exception { // Primary UFS cannot be re-mounted String ufsRoot = Configuration.get(PropertyKey.MASTER_MOUNT_TABLE_ROOT_UFS); String ufsSubdir = PathUtils.concatPath(ufsRoot, "dir1"); UnderFileSystemUtils.mkdirIfNotExists(mUfs, ufsSubdir); try { mFileSystem.mount(new AlluxioURI("/dir"), new AlluxioURI(ufsSubdir)); Assert.fail("Cannot remount primary ufs."); } catch (AlluxioException e) { // Exception expected } String alternateUfsRoot = createAlternateUfs(); try { String midDirPath = PathUtils.concatPath(alternateUfsRoot, "mid"); String innerDirPath = PathUtils.concatPath(midDirPath, "inner"); UnderFileSystemUtils.mkdirIfNotExists(mUfs, innerDirPath); mFileSystem.mount(new AlluxioURI("/mid"), new AlluxioURI(midDirPath)); // Cannot mount suffix of already-mounted directory try { mFileSystem.mount(new AlluxioURI("/inner"), new AlluxioURI(innerDirPath)); Assert.fail("Cannot mount suffix of already-mounted directory"); } catch (AlluxioException e) { // Exception expected, continue } // Cannot mount prefix of already-mounted directory try { mFileSystem.mount(new AlluxioURI("/root"), new AlluxioURI(alternateUfsRoot)); Assert.fail("Cannot mount prefix of already-mounted directory"); } catch (AlluxioException e) { // Exception expected, continue } } finally { destroyAlternateUfs(alternateUfsRoot); } } @Test public void mountShadowUfs() throws Exception { String ufsRoot = Configuration.get(PropertyKey.MASTER_MOUNT_TABLE_ROOT_UFS); String ufsSubdir = PathUtils.concatPath(ufsRoot, "dir1"); UnderFileSystemUtils.mkdirIfNotExists(mUfs, ufsSubdir); String alternateUfsRoot = createAlternateUfs(); try { String subdirPath = PathUtils.concatPath(alternateUfsRoot, "subdir"); UnderFileSystemUtils.mkdirIfNotExists(mUfs, subdirPath); // Cannot mount to path that shadows a file in the primary UFS mFileSystem.mount(new AlluxioURI("/dir1"), new AlluxioURI(subdirPath)); Assert.fail("Cannot mount to path that shadows a file in the primary UFS"); } catch (IOException e) { // Exception expected, continue } finally { destroyAlternateUfs(alternateUfsRoot); } } // Test exception cases for all FileSystem RPCs @Test public void createExistingDirectory() throws Exception { AlluxioURI path = new AlluxioURI("/dir"); mFileSystem.createDirectory(path); mThrown.expect(FileAlreadyExistsException.class); mFileSystem.createDirectory(path); } @Test public void createDirectoryOnTopOfFile() throws Exception { AlluxioURI path = new AlluxioURI("/dir"); FileSystemTestUtils.createByteFile(mFileSystem, path, CreateFileOptions.defaults(), 10); mThrown.expect(FileAlreadyExistsException.class); mFileSystem.createDirectory(path); } @Test public void createDirectoryInvalidPath() throws Exception { mThrown.expect(InvalidPathException.class); mFileSystem.createDirectory(new AlluxioURI("not a path")); } @Test public void createExistingFile() throws Exception { AlluxioURI path = new AlluxioURI("/file"); mFileSystem.createFile(path).close(); mThrown.expect(FileAlreadyExistsException.class); mFileSystem.createFile(path); } @Test public void createFileInvalidPath() throws Exception { mThrown.expect(InvalidPathException.class); mFileSystem.createFile(new AlluxioURI("not a path")); } @Test public void deleteNonexistingPath() throws Exception { mThrown.expect(FileDoesNotExistException.class); mFileSystem.delete(new AlluxioURI("/dir")); } @Test public void deleteNonexistingNestedPath() throws Exception { mThrown.expect(FileDoesNotExistException.class); mFileSystem.delete(new AlluxioURI("/dir/dir")); } @Test public void deleteNonemptyDirectory() throws Exception { AlluxioURI dir = new AlluxioURI("/dir"); mFileSystem.createDirectory(dir); mFileSystem.createFile(new AlluxioURI(PathUtils.concatPath(dir, "file"))).close(); mThrown.expect(DirectoryNotEmptyException.class); mFileSystem.delete(dir, DeleteOptions.defaults().setRecursive(false)); } @Test public void existsNonexistingPath() throws Exception { AlluxioURI path = new AlluxioURI("/path"); assertFalse(mFileSystem.exists(path)); } @Test public void existsNonexistingNestedPath() throws Exception { AlluxioURI path = new AlluxioURI("/dir/path"); assertFalse(mFileSystem.exists(path)); } @Test public void freeNonexistingPath() throws Exception { mThrown.expect(FileDoesNotExistException.class); mFileSystem.free(new AlluxioURI("/path")); } @Test public void freeNonexistingNestedPath() throws Exception { mThrown.expect(FileDoesNotExistException.class); mFileSystem.free(new AlluxioURI("/dir/path")); } @Test public void getStatusNonexistingPath() throws Exception { mThrown.expect(FileDoesNotExistException.class); mFileSystem.getStatus(new AlluxioURI("/path")); } @Test public void getStatusNonexistingNestedPath() throws Exception { mThrown.expect(FileDoesNotExistException.class); mFileSystem.getStatus(new AlluxioURI("/dir/path")); } @Test public void listStatusNonexistingPath() throws Exception { mThrown.expect(FileDoesNotExistException.class); mFileSystem.listStatus(new AlluxioURI("/path")); } @Test public void loadMetadataNonexistingPath() throws Exception { mThrown.expect(FileDoesNotExistException.class); mFileSystem.loadMetadata(new AlluxioURI("/path")); } @Test public void openFileNonexistingPath() throws Exception { AlluxioURI path = new AlluxioURI("/path"); mThrown.expect(FileDoesNotExistException.class); mFileSystem.openFile(path); } @Test public void renameNonexistingPath() throws Exception { mThrown.expect(FileDoesNotExistException.class); mFileSystem.rename(new AlluxioURI("/path1"), new AlluxioURI("/path1")); } @Test public void setAttributeNonexistingPath() throws Exception { mThrown.expect(FileDoesNotExistException.class); mFileSystem.setAttribute(new AlluxioURI("/path")); } }