/* * 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.hadoop; import alluxio.LocalAlluxioClusterResource; import alluxio.PropertyKey; import alluxio.BaseIntegrationTest; import alluxio.underfs.UnderFileSystem; import alluxio.util.io.PathUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.Path; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Ignore; import org.junit.Test; import java.io.IOException; import java.net.URI; /** * Integration tests for {@link FileSystem#rename(Path, Path)}. */ // TODO(jiri): Test persisting rename operations to UFS. public final class FileSystemRenameIntegrationTest extends BaseIntegrationTest { @ClassRule public static LocalAlluxioClusterResource sLocalAlluxioClusterResource = new LocalAlluxioClusterResource.Builder().build(); private static String sUfsRoot; private static UnderFileSystem sUfs; private static org.apache.hadoop.fs.FileSystem sTFS; private static void create(org.apache.hadoop.fs.FileSystem fs, Path path) throws IOException { FSDataOutputStream o = fs.create(path); o.writeBytes("Test Bytes"); o.close(); } /** * Deletes files in the given filesystem. * * @param fs given filesystem */ public static void cleanup(org.apache.hadoop.fs.FileSystem fs) throws IOException { FileStatus[] statuses = fs.listStatus(new Path("/")); for (FileStatus f : statuses) { fs.delete(f.getPath(), true); } } @BeforeClass public static void beforeClass() throws Exception { Configuration conf = new Configuration(); conf.set("fs.alluxio.impl", FileSystem.class.getName()); URI uri = URI.create(sLocalAlluxioClusterResource.get().getMasterURI()); sTFS = org.apache.hadoop.fs.FileSystem.get(uri, conf); sUfsRoot = alluxio.Configuration.get(PropertyKey.MASTER_MOUNT_TABLE_ROOT_UFS); sUfs = UnderFileSystem.Factory.createForRoot(); } @Test public void basicRenameTest1() throws Exception { // Rename /fileA to /fileB Path fileA = new Path("/fileA"); Path fileB = new Path("/fileB"); create(sTFS, fileA); Assert.assertTrue(sTFS.rename(fileA, fileB)); Assert.assertFalse(sTFS.exists(fileA)); Assert.assertTrue(sTFS.exists(fileB)); Assert.assertFalse(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileA"))); Assert.assertTrue(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileB"))); cleanup(sTFS); Assert.assertFalse(sTFS.exists(fileB)); Assert.assertFalse(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileB"))); } @Test public void basicRenameTest2() throws Exception { // Rename /fileA to /dirA/fileA Path fileA = new Path("/fileA"); Path dirA = new Path("/dirA"); Path finalDst = new Path("/dirA/fileA"); create(sTFS, fileA); sTFS.mkdirs(dirA); Assert.assertTrue(sTFS.rename(fileA, finalDst)); Assert.assertFalse(sTFS.exists(fileA)); Assert.assertTrue(sTFS.exists(dirA)); Assert.assertTrue(sTFS.exists(finalDst)); Assert.assertFalse(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileA"))); Assert.assertTrue(sUfs.isDirectory(PathUtils.concatPath(sUfsRoot, "dirA"))); Assert.assertTrue(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "dirA", "fileA"))); cleanup(sTFS); Assert.assertFalse(sUfs.isDirectory(PathUtils.concatPath(sUfsRoot, "dirA"))); } @Test public void basicRenameTest3() throws Exception { // Rename /fileA to /dirA/fileA without specifying the full path Path fileA = new Path("/fileA"); Path dirA = new Path("/dirA"); Path finalDst = new Path("/dirA/fileA"); create(sTFS, fileA); sTFS.mkdirs(dirA); Assert.assertTrue(sTFS.rename(fileA, dirA)); Assert.assertFalse(sTFS.exists(fileA)); Assert.assertTrue(sTFS.exists(dirA)); Assert.assertTrue(sTFS.exists(finalDst)); Assert.assertFalse(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileA"))); Assert.assertTrue(sUfs.isDirectory(PathUtils.concatPath(sUfsRoot, "dirA"))); Assert.assertTrue(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "dirA", "fileA"))); cleanup(sTFS); Assert.assertFalse(sUfs.isDirectory(PathUtils.concatPath(sUfsRoot, "dirA"))); } @Test public void basicRenameTest4() throws Exception { // Rename /fileA to /fileA Path fileA = new Path("/fileA"); create(sTFS, fileA); Assert.assertTrue(sTFS.rename(fileA, fileA)); Assert.assertTrue(sTFS.exists(fileA)); Assert.assertTrue(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileA"))); cleanup(sTFS); Assert.assertFalse(sTFS.exists(fileA)); Assert.assertFalse(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileA"))); } @Test public void basicRenameTest5() throws Exception { // Rename /fileA to /fileAfileA Path fileA = new Path("/fileA"); Path finalDst = new Path("/fileAfileA"); create(sTFS, fileA); Assert.assertTrue(sTFS.rename(fileA, finalDst)); Assert.assertFalse(sTFS.exists(fileA)); Assert.assertTrue(sTFS.exists(finalDst)); Assert.assertFalse(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileA"))); Assert.assertTrue(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileAfileA"))); cleanup(sTFS); Assert.assertFalse(sTFS.exists(finalDst)); Assert.assertFalse(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileAfileA"))); } @Test public void basicRenameTest6() throws Exception { // Rename /dirA to /dirB, /dirA/fileA should become /dirB/fileA Path dirA = new Path("/dirA"); Path dirB = new Path("/dirB"); Path fileA = new Path("/dirA/fileA"); Path finalDst = new Path("/dirB/fileA"); sTFS.mkdirs(dirA); create(sTFS, fileA); Assert.assertTrue(sTFS.rename(dirA, dirB)); Assert.assertFalse(sTFS.exists(dirA)); Assert.assertFalse(sTFS.exists(fileA)); Assert.assertTrue(sTFS.exists(dirB)); Assert.assertTrue(sTFS.exists(finalDst)); Assert.assertFalse(sUfs.isDirectory(PathUtils.concatPath(sUfsRoot, "dirA"))); Assert.assertFalse(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "dirA", "fileA"))); Assert.assertTrue(sUfs.isDirectory(PathUtils.concatPath(sUfsRoot, "dirB"))); Assert.assertTrue(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "dirB", "fileA"))); cleanup(sTFS); Assert.assertFalse(sTFS.exists(dirB)); Assert.assertFalse(sTFS.exists(finalDst)); Assert.assertFalse(sUfs.isDirectory(PathUtils.concatPath(sUfsRoot, "dirB"))); Assert.assertFalse(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "dirB", "fileA"))); } @Test @Ignore // TODO(jiri): The test logic below does not work in the presence of transparent naming. // The current implementation renames files on UFS if they are marked as persisted. They are // marked as persisted when they are closed. Thus, if the Alluxio path of the file being // written to changes before it is closed, renaming the temporary underlying file to its final // destination fails. public void basicRenameTest7() throws Exception { // Rename /dirA to /dirB, /dirA/fileA should become /dirB/fileA even if it was not closed Path dirA = new Path("/dirA"); Path dirB = new Path("/dirB"); Path fileA = new Path("/dirA/fileA"); Path finalDst = new Path("/dirB/fileA"); sTFS.mkdirs(dirA); FSDataOutputStream o = sTFS.create(fileA); o.writeBytes("Test Bytes"); // Due to Hadoop 1 support we stick with the deprecated version. If we drop support for it // FSDataOutputStream.hflush will be the new one. o.sync(); Assert.assertTrue(sTFS.rename(dirA, dirB)); Assert.assertFalse(sTFS.exists(dirA)); Assert.assertFalse(sTFS.exists(fileA)); Assert.assertTrue(sTFS.exists(dirB)); Assert.assertTrue(sTFS.exists(finalDst)); o.close(); Assert.assertFalse(sTFS.exists(dirA)); Assert.assertFalse(sTFS.exists(fileA)); Assert.assertTrue(sTFS.exists(dirB)); Assert.assertTrue(sTFS.exists(finalDst)); cleanup(sTFS); } @Test public void errorRenameTest1() throws Exception { // Rename /dirA to /dirA/dirB should fail Path dirA = new Path("/dirA"); Path finalDst = new Path("/dirA/dirB"); sTFS.mkdirs(dirA); Assert.assertFalse(sTFS.rename(dirA, finalDst)); Assert.assertFalse(sTFS.exists(finalDst)); Assert.assertTrue(sTFS.exists(dirA)); Assert.assertFalse(sUfs.isDirectory(PathUtils.concatPath(sUfsRoot, "dirA", "dirB"))); Assert.assertFalse(sUfs.isDirectory(PathUtils.concatPath(sUfsRoot, "dirB"))); cleanup(sTFS); Assert.assertFalse(sTFS.exists(dirA)); Assert.assertFalse(sUfs.isDirectory(PathUtils.concatPath(sUfsRoot, "dirB"))); } @Test public void errorRenameTest2() throws Exception { // Rename /fileA to /fileB should fail if /fileB exists Path fileA = new Path("/fileA"); Path fileB = new Path("/fileB"); create(sTFS, fileA); create(sTFS, fileB); Assert.assertFalse(sTFS.rename(fileA, fileB)); Assert.assertTrue(sTFS.exists(fileA)); Assert.assertTrue(sTFS.exists(fileB)); Assert.assertTrue(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileA"))); Assert.assertTrue(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileB"))); cleanup(sTFS); Assert.assertFalse(sTFS.exists(fileA)); Assert.assertFalse(sTFS.exists(fileB)); Assert.assertFalse(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileA"))); Assert.assertFalse(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileB"))); } @Test public void errorRenameTest3() throws Exception { // Rename /fileA to /dirA/fileA should fail if /dirA/fileA exists Path fileA = new Path("/fileA"); Path dirA = new Path("/dirA"); Path finalDst = new Path("/dirA/fileA"); create(sTFS, fileA); create(sTFS, finalDst); Assert.assertFalse(sTFS.rename(fileA, dirA)); Assert.assertTrue(sTFS.exists(fileA)); Assert.assertTrue(sTFS.exists(dirA)); Assert.assertTrue(sTFS.exists(finalDst)); Assert.assertTrue(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileA"))); Assert.assertTrue(sUfs.isDirectory(PathUtils.concatPath(sUfsRoot, "dirA"))); Assert.assertTrue(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "dirA", "fileA"))); cleanup(sTFS); Assert.assertFalse(sTFS.exists(fileA)); Assert.assertFalse(sTFS.exists(dirA)); Assert.assertFalse(sTFS.exists(finalDst)); Assert.assertFalse(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileA"))); Assert.assertFalse(sUfs.isDirectory(PathUtils.concatPath(sUfsRoot, "dirA"))); Assert.assertFalse(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "dirA", "fileA"))); } @Test public void errorRenameTest4() throws Exception { // Rename /fileA to an nonexistent path should fail Path fileA = new Path("/fileA"); Path nonexistentPath = new Path("/doesNotExist/fileA"); create(sTFS, fileA); Assert.assertFalse(sTFS.rename(fileA, nonexistentPath)); Assert.assertTrue(sTFS.exists(fileA)); Assert.assertTrue(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileA"))); cleanup(sTFS); Assert.assertFalse(sTFS.exists(fileA)); Assert.assertFalse(sUfs.isFile(PathUtils.concatPath(sUfsRoot, "fileA"))); } }