1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.apache.hadoop.fs.azure; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertFalse; 23 import static org.junit.Assert.assertNotNull; 24 import static org.junit.Assert.assertTrue; 25 26 import java.util.HashMap; 27 28 import org.apache.hadoop.fs.FileStatus; 29 import org.apache.hadoop.fs.FileSystem; 30 import org.apache.hadoop.fs.Path; 31 import org.apache.hadoop.fs.permission.FsPermission; 32 import org.junit.After; 33 import org.junit.Before; 34 import org.junit.Test; 35 36 /** 37 * Tests that WASB handles things gracefully when users add blobs to the Azure 38 * Storage container from outside WASB's control. 39 */ 40 public class TestOutOfBandAzureBlobOperations { 41 private AzureBlobStorageTestAccount testAccount; 42 private FileSystem fs; 43 private InMemoryBlockBlobStore backingStore; 44 45 @Before setUp()46 public void setUp() throws Exception { 47 testAccount = AzureBlobStorageTestAccount.createMock(); 48 fs = testAccount.getFileSystem(); 49 backingStore = testAccount.getMockStorage().getBackingStore(); 50 } 51 52 @After tearDown()53 public void tearDown() throws Exception { 54 testAccount.cleanup(); 55 fs = null; 56 backingStore = null; 57 } 58 createEmptyBlobOutOfBand(String path)59 private void createEmptyBlobOutOfBand(String path) { 60 backingStore.setContent( 61 AzureBlobStorageTestAccount.toMockUri(path), 62 new byte[] { 1, 2 }, 63 new HashMap<String, String>(), 64 false, 0); 65 } 66 67 @SuppressWarnings("deprecation") 68 @Test testImplicitFolderListed()69 public void testImplicitFolderListed() throws Exception { 70 createEmptyBlobOutOfBand("root/b"); 71 72 // List the blob itself. 73 FileStatus[] obtained = fs.listStatus(new Path("/root/b")); 74 assertNotNull(obtained); 75 assertEquals(1, obtained.length); 76 assertFalse(obtained[0].isDir()); 77 assertEquals("/root/b", obtained[0].getPath().toUri().getPath()); 78 79 // List the directory 80 obtained = fs.listStatus(new Path("/root")); 81 assertNotNull(obtained); 82 assertEquals(1, obtained.length); 83 assertFalse(obtained[0].isDir()); 84 assertEquals("/root/b", obtained[0].getPath().toUri().getPath()); 85 86 // Get the directory's file status 87 FileStatus dirStatus = fs.getFileStatus(new Path("/root")); 88 assertNotNull(dirStatus); 89 assertTrue(dirStatus.isDir()); 90 assertEquals("/root", dirStatus.getPath().toUri().getPath()); 91 } 92 93 @Test testImplicitFolderDeleted()94 public void testImplicitFolderDeleted() throws Exception { 95 createEmptyBlobOutOfBand("root/b"); 96 assertTrue(fs.exists(new Path("/root"))); 97 assertTrue(fs.delete(new Path("/root"), true)); 98 assertFalse(fs.exists(new Path("/root"))); 99 } 100 101 @Test testFileInImplicitFolderDeleted()102 public void testFileInImplicitFolderDeleted() throws Exception { 103 createEmptyBlobOutOfBand("root/b"); 104 assertTrue(fs.exists(new Path("/root"))); 105 assertTrue(fs.delete(new Path("/root/b"), true)); 106 assertTrue(fs.exists(new Path("/root"))); 107 } 108 109 @SuppressWarnings("deprecation") 110 @Test testFileAndImplicitFolderSameName()111 public void testFileAndImplicitFolderSameName() throws Exception { 112 createEmptyBlobOutOfBand("root/b"); 113 createEmptyBlobOutOfBand("root/b/c"); 114 FileStatus[] listResult = fs.listStatus(new Path("/root/b")); 115 // File should win. 116 assertEquals(1, listResult.length); 117 assertFalse(listResult[0].isDir()); 118 try { 119 // Trying to delete root/b/c would cause a dilemma for WASB, so 120 // it should throw. 121 fs.delete(new Path("/root/b/c"), true); 122 assertTrue("Should've thrown.", false); 123 } catch (AzureException e) { 124 assertEquals("File /root/b/c has a parent directory /root/b" 125 + " which is also a file. Can't resolve.", e.getMessage()); 126 } 127 } 128 129 private static enum DeepCreateTestVariation { 130 File, Folder 131 }; 132 133 /** 134 * Tests that when we create the file (or folder) x/y/z, we also create 135 * explicit folder blobs for x and x/y 136 */ 137 @Test testCreatingDeepFileCreatesExplicitFolder()138 public void testCreatingDeepFileCreatesExplicitFolder() throws Exception { 139 for (DeepCreateTestVariation variation : DeepCreateTestVariation.values()) { 140 switch (variation) { 141 case File: 142 assertTrue(fs.createNewFile(new Path("/x/y/z"))); 143 break; 144 case Folder: 145 assertTrue(fs.mkdirs(new Path("/x/y/z"))); 146 break; 147 } 148 assertTrue(backingStore 149 .exists(AzureBlobStorageTestAccount.toMockUri("x"))); 150 assertTrue(backingStore.exists(AzureBlobStorageTestAccount 151 .toMockUri("x/y"))); 152 fs.delete(new Path("/x"), true); 153 } 154 } 155 156 @Test testSetPermissionOnImplicitFolder()157 public void testSetPermissionOnImplicitFolder() throws Exception { 158 createEmptyBlobOutOfBand("root/b"); 159 FsPermission newPermission = new FsPermission((short) 0600); 160 fs.setPermission(new Path("/root"), newPermission); 161 FileStatus newStatus = fs.getFileStatus(new Path("/root")); 162 assertNotNull(newStatus); 163 assertEquals(newPermission, newStatus.getPermission()); 164 } 165 166 @Test testSetOwnerOnImplicitFolder()167 public void testSetOwnerOnImplicitFolder() throws Exception { 168 createEmptyBlobOutOfBand("root/b"); 169 fs.setOwner(new Path("/root"), "newOwner", null); 170 FileStatus newStatus = fs.getFileStatus(new Path("/root")); 171 assertNotNull(newStatus); 172 assertEquals("newOwner", newStatus.getOwner()); 173 } 174 } 175