/* * 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.worker.file; import alluxio.AlluxioURI; import alluxio.client.file.FileSystem; import alluxio.client.file.URIStatus; import alluxio.security.authorization.Mode; import alluxio.underfs.UnderFileSystem; import alluxio.underfs.options.MkdirsOptions; import alluxio.wire.FileInfo; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import java.io.IOException; /** * Tests {@link UnderFileSystemUtils}. */ @RunWith(PowerMockRunner.class) @PrepareForTest({FileSystem.class, UnderFileSystem.class}) public final class UnderFileSystemUtilsTest { private FileSystem mFileSystem; private UnderFileSystem mUnderFileSystem; // Test paths in Alluxio final AlluxioURI mAlluxioRoot = new AlluxioURI("/"); final AlluxioURI mAlluxioA = new AlluxioURI("/a"); final AlluxioURI mAlluxioB = new AlluxioURI("/a/b"); final AlluxioURI mAlluxioFile = new AlluxioURI("/a/b/file"); // Permissions for directories in Alluxio final String mOwnerRoot = "ownerRoot"; final String mOwnerA = "ownerA"; final String mOwnerB = "ownerB"; final String mGroup = "group"; final Mode mMode = Mode.createFullAccess(); // Test paths in UFS final String mUfsRoot = "/ufs"; final String mUfsA = "/ufs/a"; final String mUfsB = "/ufs/a/b"; final String mUfsFile = "/ufs/a/b/file"; /** * The exception expected to be thrown. */ @Rule public final ExpectedException mThrown = ExpectedException.none(); @Before public final void before() throws Exception { mFileSystem = PowerMockito.mock(FileSystem.class); mUnderFileSystem = PowerMockito.mock(UnderFileSystem.class); Mockito.when(mUnderFileSystem.mkdirs(Mockito.anyString(), Mockito.any(MkdirsOptions.class))) .thenReturn(true); } /** * Tests the method {@link UnderFileSystemUtils#prepareFilePath} when root is mount point. */ @Test public void prepareFilePath1() throws Exception { // Alluxio root is mount point Mockito.when(mFileSystem.getStatus(mAlluxioRoot)) .thenReturn(createStatus(mOwnerRoot, mGroup, mMode, true)); Mockito.when(mFileSystem.getStatus(mAlluxioA)) .thenReturn(createStatus(mOwnerA, mGroup, mMode, false)); Mockito.when(mFileSystem.getStatus(mAlluxioB)) .thenReturn(createStatus(mOwnerB, mGroup, mMode, false)); // Parent directories 'a' and 'b' do not exist in UFS Mockito.when(mUnderFileSystem.isDirectory(mUfsRoot)).thenReturn(true); Mockito.when(mUnderFileSystem.isDirectory(mUfsA)).thenReturn(false); Mockito.when(mUnderFileSystem.isDirectory(mUfsB)).thenReturn(false); UnderFileSystemUtils.prepareFilePath(mAlluxioFile, mUfsFile, mFileSystem, mUnderFileSystem); // Verify getStatus is called for all non-existent directories Mockito.verify(mFileSystem, Mockito.times(2)).getStatus(Mockito.any(AlluxioURI.class)); Mockito.verify(mFileSystem, Mockito.times(1)).getStatus(mAlluxioA); Mockito.verify(mFileSystem, Mockito.times(1)).getStatus(mAlluxioA); // Verify mkdir is called with the correct permissions Mockito.verify(mUnderFileSystem, Mockito.times(1)).mkdirs(mUfsA, createMkdirsOptions(mOwnerA)); Mockito.verify(mUnderFileSystem, Mockito.times(1)).mkdirs(mUfsB, createMkdirsOptions(mOwnerB)); } /** * Tests the method {@link UnderFileSystemUtils#prepareFilePath} with nested mount points. */ @Test public void prepareFilePath2() throws Exception { // Alluxio 'a' is mount point Mockito.when(mFileSystem.getStatus(mAlluxioRoot)) .thenReturn(createStatus(mOwnerRoot, mGroup, mMode, true)); Mockito.when(mFileSystem.getStatus(mAlluxioA)) .thenReturn(createStatus(mOwnerA, mGroup, mMode, true)); Mockito.when(mFileSystem.getStatus(mAlluxioB)) .thenReturn(createStatus(mOwnerB, mGroup, mMode, false)); // Parent directory 'b' does not exist in UFS Mockito.when(mUnderFileSystem.isDirectory(mUfsRoot)).thenReturn(true); Mockito.when(mUnderFileSystem.isDirectory(mUfsA)).thenReturn(true); Mockito.when(mUnderFileSystem.isDirectory(mUfsB)).thenReturn(false); UnderFileSystemUtils.prepareFilePath(mAlluxioFile, mUfsFile, mFileSystem, mUnderFileSystem); // Verify getStatus is called for all non-existent directories Mockito.verify(mFileSystem, Mockito.times(1)).getStatus(Mockito.any(AlluxioURI.class)); Mockito.verify(mFileSystem, Mockito.times(1)).getStatus(mAlluxioB); // Verify mkdir is called with the correct permissions Mockito.verify(mUnderFileSystem, Mockito.times(1)).mkdirs(mUfsB, createMkdirsOptions(mOwnerB)); } /** * Tests the method {@link UnderFileSystemUtils#prepareFilePath} with nested mount points when * the deepest parent mount point does not exist in UFS. */ @Test public void prepareFilePath3() throws Exception { // An IOException should be thrown when mount point does not exist in UFS mThrown.expect(IOException.class); // Alluxio 'a' is mount point Mockito.when(mFileSystem.getStatus(mAlluxioRoot)) .thenReturn(createStatus(mOwnerRoot, mGroup, mMode, true)); Mockito.when(mFileSystem.getStatus(mAlluxioA)) .thenReturn(createStatus(mOwnerA, mGroup, mMode, true)); Mockito.when(mFileSystem.getStatus(mAlluxioB)) .thenReturn(createStatus(mOwnerB, mGroup, mMode, false)); // Parent directories 'a' and 'b' do not exist in UFS Mockito.when(mUnderFileSystem.isDirectory(mUfsRoot)).thenReturn(true); Mockito.when(mUnderFileSystem.isDirectory(mUfsA)).thenReturn(false); Mockito.when(mUnderFileSystem.isDirectory(mUfsB)).thenReturn(false); UnderFileSystemUtils.prepareFilePath(mAlluxioFile, mUfsFile, mFileSystem, mUnderFileSystem); // Verify getStatus is called for all non-existent directories Mockito.verify(mFileSystem, Mockito.times(1)).getStatus(Mockito.any(AlluxioURI.class)); Mockito.verify(mFileSystem, Mockito.times(1)).getStatus(mAlluxioB); // Verify no directories are created in UFS Mockito.verify(mUnderFileSystem, Mockito.times(0)).mkdirs(Mockito.anyString(), Mockito.any(MkdirsOptions.class)); } private MkdirsOptions createMkdirsOptions(String owner) { return MkdirsOptions.defaults().setCreateParent(false).setOwner(owner).setGroup(mGroup) .setMode(mMode); } private URIStatus createStatus(String owner, String group, Mode mode, boolean isMountPoint) { FileInfo info = new FileInfo(); info.setMountPoint(true); info.setOwner(owner); info.setGroup(group); info.setMode(mode.toShort()); info.setMountPoint(isMountPoint); return new URIStatus(info); } }