|
@@ -22,10 +22,12 @@ import java.io.FileNotFoundException;
|
|
|
import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
import java.io.OutputStream;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.Calendar;
|
|
|
import java.util.Date;
|
|
|
+import java.util.EnumSet;
|
|
|
import java.util.TimeZone;
|
|
|
|
|
|
import org.apache.commons.logging.Log;
|
|
@@ -37,6 +39,7 @@ import org.apache.hadoop.fs.FileStatus;
|
|
|
import org.apache.hadoop.fs.FileSystem;
|
|
|
import org.apache.hadoop.fs.FileUtil;
|
|
|
import org.apache.hadoop.fs.Path;
|
|
|
+import org.apache.hadoop.fs.XAttrSetFlag;
|
|
|
import org.apache.hadoop.fs.contract.ContractTestUtils;
|
|
|
import org.apache.hadoop.fs.permission.FsPermission;
|
|
|
import org.apache.hadoop.security.UserGroupInformation;
|
|
@@ -51,6 +54,7 @@ import static org.apache.hadoop.fs.azure.integration.AzureTestUtils.readStringFr
|
|
|
import static org.apache.hadoop.fs.azure.integration.AzureTestUtils.writeStringToFile;
|
|
|
import static org.apache.hadoop.fs.azure.integration.AzureTestUtils.writeStringToStream;
|
|
|
import static org.apache.hadoop.test.GenericTestUtils.*;
|
|
|
+import static org.apache.hadoop.test.LambdaTestUtils.intercept;
|
|
|
|
|
|
/*
|
|
|
* Tests the Native Azure file system (WASB) against an actual blob store if
|
|
@@ -65,6 +69,10 @@ public abstract class NativeAzureFileSystemBaseTest
|
|
|
|
|
|
private final long modifiedTimeErrorMargin = 5 * 1000; // Give it +/-5 seconds
|
|
|
|
|
|
+ private static final short READ_WRITE_PERMISSIONS = 644;
|
|
|
+ private static final EnumSet<XAttrSetFlag> CREATE_FLAG = EnumSet.of(XAttrSetFlag.CREATE);
|
|
|
+ private static final EnumSet<XAttrSetFlag> REPLACE_FLAG = EnumSet.of(XAttrSetFlag.REPLACE);
|
|
|
+
|
|
|
public static final Log LOG = LogFactory.getLog(NativeAzureFileSystemBaseTest.class);
|
|
|
protected NativeAzureFileSystem fs;
|
|
|
|
|
@@ -117,6 +125,60 @@ public abstract class NativeAzureFileSystemBaseTest
|
|
|
fs.delete(testFile, true);
|
|
|
}
|
|
|
|
|
|
+ @Test
|
|
|
+ public void testSetGetXAttr() throws Exception {
|
|
|
+ byte[] attributeValue1 = "hi".getBytes(StandardCharsets.UTF_8);
|
|
|
+ byte[] attributeValue2 = "你好".getBytes(StandardCharsets.UTF_8);
|
|
|
+ String attributeName1 = "user.asciiAttribute";
|
|
|
+ String attributeName2 = "user.unicodeAttribute";
|
|
|
+ Path testFile = methodPath();
|
|
|
+
|
|
|
+ // after creating a file, the xAttr should not be present
|
|
|
+ createEmptyFile(testFile, FsPermission.createImmutable(READ_WRITE_PERMISSIONS));
|
|
|
+ assertNull(fs.getXAttr(testFile, attributeName1));
|
|
|
+
|
|
|
+ // after setting the xAttr on the file, the value should be retrievable
|
|
|
+ fs.setXAttr(testFile, attributeName1, attributeValue1);
|
|
|
+ assertArrayEquals(attributeValue1, fs.getXAttr(testFile, attributeName1));
|
|
|
+
|
|
|
+ // after setting a second xAttr on the file, the first xAttr values should not be overwritten
|
|
|
+ fs.setXAttr(testFile, attributeName2, attributeValue2);
|
|
|
+ assertArrayEquals(attributeValue1, fs.getXAttr(testFile, attributeName1));
|
|
|
+ assertArrayEquals(attributeValue2, fs.getXAttr(testFile, attributeName2));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testSetGetXAttrCreateReplace() throws Exception {
|
|
|
+ byte[] attributeValue = "one".getBytes(StandardCharsets.UTF_8);
|
|
|
+ String attributeName = "user.someAttribute";
|
|
|
+ Path testFile = methodPath();
|
|
|
+
|
|
|
+ // after creating a file, it must be possible to create a new xAttr
|
|
|
+ createEmptyFile(testFile, FsPermission.createImmutable(READ_WRITE_PERMISSIONS));
|
|
|
+ fs.setXAttr(testFile, attributeName, attributeValue, CREATE_FLAG);
|
|
|
+ assertArrayEquals(attributeValue, fs.getXAttr(testFile, attributeName));
|
|
|
+
|
|
|
+ // however after the xAttr is created, creating it again must fail
|
|
|
+ intercept(IOException.class, () -> fs.setXAttr(testFile, attributeName, attributeValue, CREATE_FLAG));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testSetGetXAttrReplace() throws Exception {
|
|
|
+ byte[] attributeValue1 = "one".getBytes(StandardCharsets.UTF_8);
|
|
|
+ byte[] attributeValue2 = "two".getBytes(StandardCharsets.UTF_8);
|
|
|
+ String attributeName = "user.someAttribute";
|
|
|
+ Path testFile = methodPath();
|
|
|
+
|
|
|
+ // after creating a file, it must not be possible to replace an xAttr
|
|
|
+ createEmptyFile(testFile, FsPermission.createImmutable(READ_WRITE_PERMISSIONS));
|
|
|
+ intercept(IOException.class, () -> fs.setXAttr(testFile, attributeName, attributeValue1, REPLACE_FLAG));
|
|
|
+
|
|
|
+ // however after the xAttr is created, replacing it must succeed
|
|
|
+ fs.setXAttr(testFile, attributeName, attributeValue1, CREATE_FLAG);
|
|
|
+ fs.setXAttr(testFile, attributeName, attributeValue2, REPLACE_FLAG);
|
|
|
+ assertArrayEquals(attributeValue2, fs.getXAttr(testFile, attributeName));
|
|
|
+ }
|
|
|
+
|
|
|
@Test
|
|
|
public void testStoreDeleteFolder() throws Exception {
|
|
|
Path testFolder = methodPath();
|