/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.hadoop.hdfs.server.namenode;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;

import org.apache.hadoop.HadoopIllegalArgumentException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.XAttrSetFlag;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.hdfs.DFSTestUtil;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.HdfsConfiguration;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.ipc.RemoteException;
import org.apache.hadoop.test.GenericTestUtils;

import static org.apache.hadoop.fs.permission.AclEntryScope.ACCESS;
import static org.apache.hadoop.fs.permission.AclEntryType.USER;
import static org.apache.hadoop.fs.permission.FsAction.ALL;
import static org.apache.hadoop.fs.permission.FsAction.READ;
import static org.apache.hadoop.hdfs.server.namenode.AclTestHelpers.aclEntry;
import static org.apache.hadoop.hdfs.server.common.HdfsServerConstants.SECURITY_XATTR_UNREADABLE_BY_SUPERUSER;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import org.apache.hadoop.thirdparty.com.google.common.collect.Lists;
import org.apache.hadoop.thirdparty.com.google.common.collect.Maps;

/**
 * Tests NameNode interaction for all XAttr APIs.
 * This test suite covers restarting the NN, saving a new checkpoint. 
 */
public class FSXAttrBaseTest {

  protected static MiniDFSCluster dfsCluster;
  protected static Configuration conf;
  private static int pathCount = 0;
  protected static Path path;
  protected static Path filePath;
  protected static Path rawPath;
  protected static Path rawFilePath;

  // XAttrs
  protected static final String name1 = "user.a1";
  protected static final byte[] value1 = {0x31, 0x32, 0x33};
  protected static final byte[] newValue1 = {0x31, 0x31, 0x31};
  protected static final String name2 = "user.a2";
  protected static final byte[] value2 = {0x37, 0x38, 0x39};
  protected static final String name3 = "user.a3";
  protected static final String name4 = "user.a4";
  protected static final String raw1 = "raw.a1";
  protected static final String raw2 = "raw.a2";
  protected static final String security1 =
      SECURITY_XATTR_UNREADABLE_BY_SUPERUSER;

  private static final int MAX_SIZE = security1.length();

  protected FileSystem fs;

  private static final UserGroupInformation BRUCE =
      UserGroupInformation.createUserForTesting("bruce", new String[] { });
  private static final UserGroupInformation DIANA =
      UserGroupInformation.createUserForTesting("diana", new String[] { });

  @BeforeClass
  public static void init() throws Exception {
    conf = new HdfsConfiguration();
    conf.setBoolean(DFSConfigKeys.DFS_NAMENODE_XATTRS_ENABLED_KEY, true);
    conf.setBoolean(DFSConfigKeys.DFS_NAMENODE_ACLS_ENABLED_KEY, true);
    conf.setInt(DFSConfigKeys.DFS_NAMENODE_MAX_XATTRS_PER_INODE_KEY, 3);
    conf.setInt(DFSConfigKeys.DFS_NAMENODE_MAX_XATTR_SIZE_KEY, MAX_SIZE);
    initCluster(true);
  }

  @AfterClass
  public static void shutdown() {
    if (dfsCluster != null) {
      dfsCluster.shutdown();
    }
  }

  @Before
  public void setUp() throws Exception {
    pathCount += 1;
    path = new Path("/p" + pathCount);
    filePath = new Path(path, "file");
    rawPath = new Path("/.reserved/raw/p" + pathCount);
    rawFilePath = new Path(rawPath, "file");
    initFileSystem();
  }

  @After
  public void destroyFileSystems() {
    IOUtils.cleanup(null, fs);
    fs = null;
  }
  
  /**
   * Tests for creating xattr
   * 1. Create an xattr using XAttrSetFlag.CREATE.
   * 2. Create an xattr which already exists and expect an exception.
   * 3. Create multiple xattrs.
   * 4. Restart NN and save checkpoint scenarios.
   */
  @Test(timeout = 120000)
  public void testCreateXAttr() throws Exception {
    Map<String, byte[]> expectedXAttrs = Maps.newHashMap();
    expectedXAttrs.put(name1, value1);
    expectedXAttrs.put(name2, null);
    expectedXAttrs.put(security1, null);
    doTestCreateXAttr(filePath, expectedXAttrs);
    expectedXAttrs.put(raw1, value1);
    doTestCreateXAttr(rawFilePath, expectedXAttrs);
  }

  private void doTestCreateXAttr(Path usePath, Map<String,
      byte[]> expectedXAttrs) throws Exception {
    DFSTestUtil.createFile(fs, usePath, 8192, (short) 1, 0xFEED);
    fs.setXAttr(usePath, name1, value1, EnumSet.of(XAttrSetFlag.CREATE));

    Map<String, byte[]> xattrs = fs.getXAttrs(usePath);
    Assert.assertEquals(xattrs.size(), 1);
    Assert.assertArrayEquals(value1, xattrs.get(name1));
    
    fs.removeXAttr(usePath, name1);
    
    xattrs = fs.getXAttrs(usePath);
    Assert.assertEquals(xattrs.size(), 0);
    
    // Create xattr which already exists.
    fs.setXAttr(usePath, name1, value1, EnumSet.of(XAttrSetFlag.CREATE));
    try {
      fs.setXAttr(usePath, name1, value1, EnumSet.of(XAttrSetFlag.CREATE));
      Assert.fail("Creating xattr which already exists should fail.");
    } catch (IOException e) {
    }
    fs.removeXAttr(usePath, name1);
    
    // Create the xattrs
    for (Map.Entry<String, byte[]> ent : expectedXAttrs.entrySet()) {
      fs.setXAttr(usePath, ent.getKey(), ent.getValue(),
          EnumSet.of(XAttrSetFlag.CREATE));
    }
    xattrs = fs.getXAttrs(usePath);
    Assert.assertEquals(xattrs.size(), expectedXAttrs.size());
    for (Map.Entry<String, byte[]> ent : expectedXAttrs.entrySet()) {
      final byte[] val =
          (ent.getValue() == null) ? new byte[0] : ent.getValue();
      Assert.assertArrayEquals(val, xattrs.get(ent.getKey()));
    }
    
    restart(false);
    initFileSystem();
    xattrs = fs.getXAttrs(usePath);
    Assert.assertEquals(xattrs.size(), expectedXAttrs.size());
    for (Map.Entry<String, byte[]> ent : expectedXAttrs.entrySet()) {
      final byte[] val =
          (ent.getValue() == null) ? new byte[0] : ent.getValue();
      Assert.assertArrayEquals(val, xattrs.get(ent.getKey()));
    }
    
    restart(true);
    initFileSystem();
    xattrs = fs.getXAttrs(usePath);
    Assert.assertEquals(xattrs.size(), expectedXAttrs.size());
    for (Map.Entry<String, byte[]> ent : expectedXAttrs.entrySet()) {
      final byte[] val =
          (ent.getValue() == null) ? new byte[0] : ent.getValue();
      Assert.assertArrayEquals(val, xattrs.get(ent.getKey()));
    }

    fs.delete(usePath, false);
  }
  
  /**
   * Tests for replacing xattr
   * 1. Replace an xattr using XAttrSetFlag.REPLACE.
   * 2. Replace an xattr which doesn't exist and expect an exception.
   * 3. Create multiple xattrs and replace some.
   * 4. Restart NN and save checkpoint scenarios.
   */
  @Test(timeout = 120000)
  public void testReplaceXAttr() throws Exception {
    FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
    fs.setXAttr(path, name1, value1, EnumSet.of(XAttrSetFlag.CREATE));
    fs.setXAttr(path, name1, newValue1, EnumSet.of(XAttrSetFlag.REPLACE));
    
    Map<String, byte[]> xattrs = fs.getXAttrs(path);
    Assert.assertEquals(xattrs.size(), 1);
    Assert.assertArrayEquals(newValue1, xattrs.get(name1));
    
    fs.removeXAttr(path, name1);
    
    // Replace xattr which does not exist.
    try {
      fs.setXAttr(path, name1, value1, EnumSet.of(XAttrSetFlag.REPLACE));
      Assert.fail("Replacing xattr which does not exist should fail.");
    } catch (IOException e) {
    }
    
    // Create two xattrs, then replace one
    fs.setXAttr(path, name1, value1, EnumSet.of(XAttrSetFlag.CREATE));
    fs.setXAttr(path, name2, value2, EnumSet.of(XAttrSetFlag.CREATE));
    fs.setXAttr(path, name2, null, EnumSet.of(XAttrSetFlag.REPLACE));
    xattrs = fs.getXAttrs(path);
    Assert.assertEquals(xattrs.size(), 2);
    Assert.assertArrayEquals(value1, xattrs.get(name1));
    Assert.assertArrayEquals(new byte[0], xattrs.get(name2));
    
    restart(false);
    initFileSystem();
    xattrs = fs.getXAttrs(path);
    Assert.assertEquals(xattrs.size(), 2);
    Assert.assertArrayEquals(value1, xattrs.get(name1));
    Assert.assertArrayEquals(new byte[0], xattrs.get(name2));
    
    restart(true);
    initFileSystem();
    xattrs = fs.getXAttrs(path);
    Assert.assertEquals(xattrs.size(), 2);
    Assert.assertArrayEquals(value1, xattrs.get(name1));
    Assert.assertArrayEquals(new byte[0], xattrs.get(name2));
    
    fs.removeXAttr(path, name1);
    fs.removeXAttr(path, name2);
  }
  
  /**
   * Tests for setting xattr
   * 1. Set xattr with XAttrSetFlag.CREATE|XAttrSetFlag.REPLACE flag.
   * 2. Set xattr with illegal name.
   * 3. Set xattr without XAttrSetFlag.
   * 4. Set xattr and total number exceeds max limit.
   * 5. Set xattr and name is too long.
   * 6. Set xattr and value is too long.
   */
  @Test(timeout = 120000)
  public void testSetXAttr() throws Exception {
    FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
    fs.setXAttr(path, name1, value1, EnumSet.of(XAttrSetFlag.CREATE, 
        XAttrSetFlag.REPLACE));
        
    Map<String, byte[]> xattrs = fs.getXAttrs(path);
    Assert.assertEquals(xattrs.size(), 1);
    Assert.assertArrayEquals(value1, xattrs.get(name1));
    fs.removeXAttr(path, name1);
    
    // Set xattr with null name
    try {
      fs.setXAttr(path, null, value1, EnumSet.of(XAttrSetFlag.CREATE, 
          XAttrSetFlag.REPLACE));
      Assert.fail("Setting xattr with null name should fail.");
    } catch (NullPointerException e) {
      GenericTestUtils.assertExceptionContains("XAttr name cannot be null", e);
    } catch (RemoteException e) {
      GenericTestUtils.assertExceptionContains("Required param xattr.name for "
          + "op: SETXATTR is null or empty", e);
    }
    
    // Set xattr with empty name: "user."
    try {
      fs.setXAttr(path, "user.", value1, EnumSet.of(XAttrSetFlag.CREATE, 
          XAttrSetFlag.REPLACE));
      Assert.fail("Setting xattr with empty name should fail.");
    } catch (RemoteException e) {
      assertEquals("Unexpected RemoteException: " + e, e.getClassName(),
          HadoopIllegalArgumentException.class.getCanonicalName());
      GenericTestUtils.assertExceptionContains("XAttr name cannot be empty", e);
    } catch (HadoopIllegalArgumentException e) {
      GenericTestUtils.assertExceptionContains("XAttr name cannot be empty", e);
    }
    
    // Set xattr with invalid name: "a1"
    try {
      fs.setXAttr(path, "a1", value1, EnumSet.of(XAttrSetFlag.CREATE, 
          XAttrSetFlag.REPLACE));
      Assert.fail("Setting xattr with invalid name prefix or without " +
          "name prefix should fail.");
    } catch (RemoteException e) {
      assertEquals("Unexpected RemoteException: " + e, e.getClassName(),
          HadoopIllegalArgumentException.class.getCanonicalName());
      GenericTestUtils.assertExceptionContains("XAttr name must be prefixed", e);
    } catch (HadoopIllegalArgumentException e) {
      GenericTestUtils.assertExceptionContains("XAttr name must be prefixed", e);
    }
    
    // Set xattr without XAttrSetFlag
    fs.setXAttr(path, name1, value1);
    xattrs = fs.getXAttrs(path);
    Assert.assertEquals(xattrs.size(), 1);
    Assert.assertArrayEquals(value1, xattrs.get(name1));
    fs.removeXAttr(path, name1);
    
    // XAttr exists, and replace it using CREATE|REPLACE flag.
    fs.setXAttr(path, name1, value1, EnumSet.of(XAttrSetFlag.CREATE));
    fs.setXAttr(path, name1, newValue1, EnumSet.of(XAttrSetFlag.CREATE, 
        XAttrSetFlag.REPLACE));
    
    xattrs = fs.getXAttrs(path);
    Assert.assertEquals(xattrs.size(), 1);
    Assert.assertArrayEquals(newValue1, xattrs.get(name1));
    
    fs.removeXAttr(path, name1);
    
    // Total number exceeds max limit
    fs.setXAttr(path, name1, value1);
    fs.setXAttr(path, name2, value2);
    fs.setXAttr(path, name3, null);
    try {
      fs.setXAttr(path, name4, null);
      Assert.fail("Setting xattr should fail if total number of xattrs " +
          "for inode exceeds max limit.");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("Cannot add additional XAttr", e);
    }
    fs.removeXAttr(path, name1);
    fs.removeXAttr(path, name2);
    fs.removeXAttr(path, name3);
    
    // Name length exceeds max limit
    String longName = "user.0123456789abcdefX0123456789abcdefX0123456789abcdef";
    try {
      fs.setXAttr(path, longName, null);
      Assert.fail("Setting xattr should fail if name is too long.");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("XAttr is too big", e);
      GenericTestUtils.assertExceptionContains("total size is 50", e);
    }

    // Value length exceeds max limit
    byte[] longValue = new byte[MAX_SIZE];
    try {
      fs.setXAttr(path, "user.a", longValue);
      Assert.fail("Setting xattr should fail if value is too long.");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("XAttr is too big", e);
      GenericTestUtils.assertExceptionContains("total size is 38", e);
    }

    // Name + value exactly equal the limit
    String name = "user.111";
    byte[] value = new byte[MAX_SIZE-3];
    fs.setXAttr(path, name, value);
  }
  
  /**
   * getxattr tests. Test that getxattr throws an exception if any of
   * the following are true:
   * an xattr that was requested doesn't exist
   * the caller specifies an unknown namespace
   * the caller doesn't have access to the namespace
   * the caller doesn't have permission to get the value of the xattr
   * the caller does not have search access to the parent directory
   * the caller has only read access to the owning directory
   * the caller has only search access to the owning directory and
   * execute/search access to the actual entity
   * the caller does not have search access to the owning directory and read
   * access to the actual entity
   */
  @Test(timeout = 120000)
  public void testGetXAttrs() throws Exception {
    FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
    fs.setXAttr(path, name1, value1, EnumSet.of(XAttrSetFlag.CREATE));
    fs.setXAttr(path, name2, value2, EnumSet.of(XAttrSetFlag.CREATE));

    final byte[] theValue = fs.getXAttr(path, "USER.a2");
    Assert.assertArrayEquals(value2, theValue);

    /* An XAttr that was requested does not exist. */
    try {
      final byte[] value = fs.getXAttr(path, name3);
      Assert.fail("expected IOException");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains(
          "At least one of the attributes provided was not found.", e);
    }
    
    /* Throw an exception if an xattr that was requested does not exist. */
    {
      final List<String> names = Lists.newArrayList();
      names.add(name1);
      names.add(name2);
      names.add(name3);
      try {
        final Map<String, byte[]> xattrs = fs.getXAttrs(path, names);
        Assert.fail("expected IOException");
      } catch (IOException e) {
        GenericTestUtils.assertExceptionContains(
            "At least one of the attributes provided was not found.", e);
      }
    }
    
    fs.removeXAttr(path, name1);
    fs.removeXAttr(path, name2);

    /* Unknown namespace should throw an exception. */
    try {
      final byte[] xattr = fs.getXAttr(path, "wackynamespace.foo");
      Assert.fail("expected IOException");
    } catch (Exception e) {
      GenericTestUtils.assertExceptionContains
          ("An XAttr name must be prefixed with " +
           "user/trusted/security/system/raw, " +
           "followed by a '.'",
          e);
    }

    /*
     * The 'trusted' namespace should not be accessible and should throw an
     * exception.
     */
    final UserGroupInformation user = UserGroupInformation.
        createUserForTesting("user", new String[] {"mygroup"});
    fs.setXAttr(path, "trusted.foo", "1234".getBytes());
    try {
      user.doAs(new PrivilegedExceptionAction<Object>() {
          @Override
          public Object run() throws Exception {
            final FileSystem userFs = dfsCluster.getFileSystem();
            final byte[] xattr = userFs.getXAttr(path, "trusted.foo");
            return null;
          }
        });
      Assert.fail("expected IOException");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("User doesn't have permission", e);
    }

    fs.setXAttr(path, name1, "1234".getBytes());

    /*
     * Test that an exception is thrown if the caller doesn't have permission to
     * get the value of the xattr.
     */

    /* Set access so that only the owner has access. */
    fs.setPermission(path, new FsPermission((short) 0700));
    try {
      user.doAs(new PrivilegedExceptionAction<Object>() {
          @Override
          public Object run() throws Exception {
            final FileSystem userFs = dfsCluster.getFileSystem();
            final byte[] xattr = userFs.getXAttr(path, name1);
            return null;
          }
        });
      Assert.fail("expected IOException");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("Permission denied", e);
    }

    /*
     * The caller must have search access to the parent directory.
     */
    final Path childDir = new Path(path, "child" + pathCount);
    /* Set access to parent so that only the owner has access. */
    FileSystem.mkdirs(fs, childDir, FsPermission.createImmutable((short)0700));
    fs.setXAttr(childDir, name1, "1234".getBytes());
    try {
      user.doAs(new PrivilegedExceptionAction<Object>() {
          @Override
          public Object run() throws Exception {
            final FileSystem userFs = dfsCluster.getFileSystem();
            final byte[] xattr = userFs.getXAttr(childDir, name1);
            return null;
          }
        });
      Assert.fail("expected IOException");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("Permission denied", e);
    }

    /* Check that read access to the owning directory is not good enough. */
    fs.setPermission(path, new FsPermission((short) 0704));
    try {
      user.doAs(new PrivilegedExceptionAction<Object>() {
          @Override
          public Object run() throws Exception {
            final FileSystem userFs = dfsCluster.getFileSystem();
            final byte[] xattr = userFs.getXAttr(childDir, name1);
            return null;
          }
        });
      Assert.fail("expected IOException");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("Permission denied", e);
    }

    /*
     * Check that search access to the owning directory and search/execute
     * access to the actual entity with extended attributes is not good enough.
     */
    fs.setPermission(path, new FsPermission((short) 0701));
    fs.setPermission(childDir, new FsPermission((short) 0701));
    try {
      user.doAs(new PrivilegedExceptionAction<Object>() {
          @Override
          public Object run() throws Exception {
            final FileSystem userFs = dfsCluster.getFileSystem();
            final byte[] xattr = userFs.getXAttr(childDir, name1);
            return null;
          }
        });
      Assert.fail("expected IOException");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("Permission denied", e);
    }

    /*
     * Check that search access to the owning directory and read access to
     * the actual entity with the extended attribute is good enough.
     */
    fs.setPermission(path, new FsPermission((short) 0701));
    fs.setPermission(childDir, new FsPermission((short) 0704));
    user.doAs(new PrivilegedExceptionAction<Object>() {
        @Override
        public Object run() throws Exception {
          final FileSystem userFs = dfsCluster.getFileSystem();
          final byte[] xattr = userFs.getXAttr(childDir, name1);
          return null;
        }
      });
  }
  
  /**
   * Tests for removing xattr
   * 1. Remove xattr.
   * 2. Restart NN and save checkpoint scenarios.
   */
  @Test(timeout = 120000)
  public void testRemoveXAttr() throws Exception {
    FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
    fs.setXAttr(path, name1, value1, EnumSet.of(XAttrSetFlag.CREATE));
    fs.setXAttr(path, name2, value2, EnumSet.of(XAttrSetFlag.CREATE));
    fs.setXAttr(path, name3, null, EnumSet.of(XAttrSetFlag.CREATE));
    
    fs.removeXAttr(path, name1);
    fs.removeXAttr(path, name2);
    
    Map<String, byte[]> xattrs = fs.getXAttrs(path);
    Assert.assertEquals(xattrs.size(), 1);
    Assert.assertArrayEquals(new byte[0], xattrs.get(name3));
    
    restart(false);
    initFileSystem();
    xattrs = fs.getXAttrs(path);
    Assert.assertEquals(xattrs.size(), 1);
    Assert.assertArrayEquals(new byte[0], xattrs.get(name3));
    
    restart(true);
    initFileSystem();
    xattrs = fs.getXAttrs(path);
    Assert.assertEquals(xattrs.size(), 1);
    Assert.assertArrayEquals(new byte[0], xattrs.get(name3));
    
    fs.removeXAttr(path, name3);
  }

  /**
   * removexattr tests. Test that removexattr throws an exception if any of
   * the following are true:
   * an xattr that was requested doesn't exist
   * the caller specifies an unknown namespace
   * the caller doesn't have access to the namespace
   * the caller doesn't have permission to get the value of the xattr
   * the caller does not have "execute" (scan) access to the parent directory
   * the caller has only read access to the owning directory
   * the caller has only execute access to the owning directory and execute
   * access to the actual entity
   * the caller does not have execute access to the owning directory and write
   * access to the actual entity
   */
  @Test(timeout = 120000)
  public void testRemoveXAttrPermissions() throws Exception {
    FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
    fs.setXAttr(path, name1, value1, EnumSet.of(XAttrSetFlag.CREATE));
    fs.setXAttr(path, name2, value2, EnumSet.of(XAttrSetFlag.CREATE));
    fs.setXAttr(path, name3, null, EnumSet.of(XAttrSetFlag.CREATE));

    try {
      fs.removeXAttr(path, name2);
      fs.removeXAttr(path, name2);
      Assert.fail("expected IOException");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("No matching attributes found", e);
    }

    /* Unknown namespace should throw an exception. */
    final String expectedExceptionString = "An XAttr name must be prefixed " +
        "with user/trusted/security/system/raw, followed by a '.'";
    try {
      fs.removeXAttr(path, "wackynamespace.foo");
      Assert.fail("expected IOException");
    } catch (RemoteException e) {
      assertEquals("Unexpected RemoteException: " + e, e.getClassName(),
          HadoopIllegalArgumentException.class.getCanonicalName());
      GenericTestUtils.assertExceptionContains(expectedExceptionString, e);
    } catch (HadoopIllegalArgumentException e) {
      GenericTestUtils.assertExceptionContains(expectedExceptionString, e);
    }

    /*
     * The 'trusted' namespace should not be accessible and should throw an
     * exception.
     */
    final UserGroupInformation user = UserGroupInformation.
        createUserForTesting("user", new String[] {"mygroup"});
    fs.setXAttr(path, "trusted.foo", "1234".getBytes());
    try {
      user.doAs(new PrivilegedExceptionAction<Object>() {
          @Override
          public Object run() throws Exception {
            final FileSystem userFs = dfsCluster.getFileSystem();
            userFs.removeXAttr(path, "trusted.foo");
            return null;
          }
        });
      Assert.fail("expected IOException");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("User doesn't have permission", e);
    } finally {
      fs.removeXAttr(path, "trusted.foo");
    }

    /*
     * Test that an exception is thrown if the caller doesn't have permission to
     * get the value of the xattr.
     */

    /* Set access so that only the owner has access. */
    fs.setPermission(path, new FsPermission((short) 0700));
    try {
      user.doAs(new PrivilegedExceptionAction<Object>() {
          @Override
          public Object run() throws Exception {
            final FileSystem userFs = dfsCluster.getFileSystem();
            userFs.removeXAttr(path, name1);
            return null;
          }
        });
      Assert.fail("expected IOException");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("Permission denied", e);
    }

    /*
     * The caller must have "execute" (scan) access to the parent directory.
     */
    final Path childDir = new Path(path, "child" + pathCount);
    /* Set access to parent so that only the owner has access. */
    FileSystem.mkdirs(fs, childDir, FsPermission.createImmutable((short)0700));
    fs.setXAttr(childDir, name1, "1234".getBytes());
    try {
      user.doAs(new PrivilegedExceptionAction<Object>() {
          @Override
          public Object run() throws Exception {
            final FileSystem userFs = dfsCluster.getFileSystem();
            userFs.removeXAttr(childDir, name1);
            return null;
          }
        });
      Assert.fail("expected IOException");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("Permission denied", e);
    }

    /* Check that read access to the owning directory is not good enough. */
    fs.setPermission(path, new FsPermission((short) 0704));
    try {
      user.doAs(new PrivilegedExceptionAction<Object>() {
          @Override
          public Object run() throws Exception {
            final FileSystem userFs = dfsCluster.getFileSystem();
            userFs.removeXAttr(childDir, name1);
            return null;
          }
        });
      Assert.fail("expected IOException");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("Permission denied", e);
    }

    /*
     * Check that execute access to the owning directory and scan access to
     * the actual entity with extended attributes is not good enough.
     */
    fs.setPermission(path, new FsPermission((short) 0701));
    fs.setPermission(childDir, new FsPermission((short) 0701));
    try {
      user.doAs(new PrivilegedExceptionAction<Object>() {
          @Override
          public Object run() throws Exception {
            final FileSystem userFs = dfsCluster.getFileSystem();
            userFs.removeXAttr(childDir, name1);
            return null;
          }
        });
      Assert.fail("expected IOException");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("Permission denied", e);
    }

    /*
     * Check that execute access to the owning directory and write access to
     * the actual entity with extended attributes is good enough.
     */
    fs.setPermission(path, new FsPermission((short) 0701));
    fs.setPermission(childDir, new FsPermission((short) 0706));
    user.doAs(new PrivilegedExceptionAction<Object>() {
        @Override
        public Object run() throws Exception {
          final FileSystem userFs = dfsCluster.getFileSystem();
          userFs.removeXAttr(childDir, name1);
          return null;
        }
      });
  }

  @Test(timeout = 120000)
  public void testRenameFileWithXAttr() throws Exception {
    FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
    fs.setXAttr(path, name1, value1, EnumSet.of(XAttrSetFlag.CREATE));
    fs.setXAttr(path, name2, value2, EnumSet.of(XAttrSetFlag.CREATE));
    Path renamePath = new Path(path.toString() + "-rename");
    fs.rename(path, renamePath);
    Map<String, byte[]> xattrs = fs.getXAttrs(renamePath);
    Assert.assertEquals(xattrs.size(), 2);
    Assert.assertArrayEquals(value1, xattrs.get(name1));
    Assert.assertArrayEquals(value2, xattrs.get(name2));
    fs.removeXAttr(renamePath, name1);
    fs.removeXAttr(renamePath, name2);
  }

  /**
   * Test the listXAttrs api.
   * listXAttrs on a path that doesn't exist.
   * listXAttrs on a path with no XAttrs
   * Check basic functionality.
   * Check that read access to parent dir is not enough to get xattr names
   * Check that write access to the parent dir is not enough to get names
   * Check that execute/scan access to the parent dir is sufficient to get
   *  xattr names.
   */
  @Test(timeout = 120000)
  public void testListXAttrs() throws Exception {
    final UserGroupInformation user = UserGroupInformation.
      createUserForTesting("user", new String[] {"mygroup"});

    /* listXAttrs in a path that doesn't exist. */
    try {
      fs.listXAttrs(path);
      fail("expected FileNotFoundException");
    } catch (FileNotFoundException e) {
      GenericTestUtils.assertExceptionContains("cannot find", e);
    }

    FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short) 0750));

    /* listXAttrs on a path with no XAttrs.*/
    final List<String> noXAttrs = fs.listXAttrs(path);
    assertTrue("XAttrs were found?", noXAttrs.size() == 0);

    fs.setXAttr(path, name1, value1, EnumSet.of(XAttrSetFlag.CREATE));
    fs.setXAttr(path, name2, value2, EnumSet.of(XAttrSetFlag.CREATE));

    /** Check basic functionality. */
    final List<String> xattrNames = fs.listXAttrs(path);
    assertTrue(xattrNames.contains(name1));
    assertTrue(xattrNames.contains(name2));
    assertTrue(xattrNames.size() == 2);

    /* Check that read access to parent dir is not enough to get xattr names. */
    fs.setPermission(path, new FsPermission((short) 0704));
    final Path childDir = new Path(path, "child" + pathCount);
    FileSystem.mkdirs(fs, childDir, FsPermission.createImmutable((short) 0700));
    fs.setXAttr(childDir, name1, "1234".getBytes());
    try {
      user.doAs(new PrivilegedExceptionAction<Object>() {
          @Override
          public Object run() throws Exception {
            final FileSystem userFs = dfsCluster.getFileSystem();
            userFs.listXAttrs(childDir);
            return null;
          }
        });
      fail("expected IOException");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("Permission denied", e);
    }

    /*
     * Check that write access to the parent dir is not enough to get names.
     */
    fs.setPermission(path, new FsPermission((short) 0702));
    try {
      user.doAs(new PrivilegedExceptionAction<Object>() {
          @Override
          public Object run() throws Exception {
            final FileSystem userFs = dfsCluster.getFileSystem();
            userFs.listXAttrs(childDir);
            return null;
          }
        });
      fail("expected IOException");
    } catch (IOException e) {
      GenericTestUtils.assertExceptionContains("Permission denied", e);
    }

    /*
     * Check that execute/scan access to the parent dir is not
     * sufficient to get xattr names.
     */
    fs.setPermission(path, new FsPermission((short) 0701));
    user.doAs(new PrivilegedExceptionAction<Object>() {
        @Override
        public Object run() throws Exception {
        try {
          final FileSystem userFs = dfsCluster.getFileSystem();
          userFs.listXAttrs(childDir);
          fail("expected AccessControlException");
        } catch (AccessControlException ace) {
          GenericTestUtils.assertExceptionContains("Permission denied", ace);
        }
        return null;
      }
      });

    /*
     * Test that xattrs in the "trusted" namespace are filtered correctly.
     */
    // Allow the user to read child path.
    fs.setPermission(childDir, new FsPermission((short) 0704));
    fs.setXAttr(childDir, "trusted.myxattr", "1234".getBytes());
    user.doAs(new PrivilegedExceptionAction<Object>() {
        @Override
        public Object run() throws Exception {
          final FileSystem userFs = dfsCluster.getFileSystem();
          List<String> xattrs = userFs.listXAttrs(childDir);
          assertTrue(xattrs.size() == 1);
          assertEquals(name1, xattrs.get(0));
          return null;
        }
      });

    assertTrue(fs.listXAttrs(childDir).size() == 2);
  }
  
  /**
   * Steps:
   * 1) Set xattrs on a file.
   * 2) Remove xattrs from that file.
   * 3) Save a checkpoint and restart NN.
   * 4) Set xattrs again on the same file.
   * 5) Remove xattrs from that file.
   * 6) Restart NN without saving a checkpoint.
   * 7) Set xattrs again on the same file.
   */
  @Test(timeout = 120000)
  public void testCleanupXAttrs() throws Exception {
    FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
    fs.setXAttr(path, name1, value1, EnumSet.of(XAttrSetFlag.CREATE));
    fs.setXAttr(path, name2, value2, EnumSet.of(XAttrSetFlag.CREATE));
    fs.removeXAttr(path, name1);
    fs.removeXAttr(path, name2);
    
    restart(true);
    initFileSystem();
    
    fs.setXAttr(path, name1, value1, EnumSet.of(XAttrSetFlag.CREATE));
    fs.setXAttr(path, name2, value2, EnumSet.of(XAttrSetFlag.CREATE));
    fs.removeXAttr(path, name1);
    fs.removeXAttr(path, name2);
    
    restart(false);
    initFileSystem();
    
    fs.setXAttr(path, name1, value1, EnumSet.of(XAttrSetFlag.CREATE));
    fs.setXAttr(path, name2, value2, EnumSet.of(XAttrSetFlag.CREATE));
    fs.removeXAttr(path, name1);
    fs.removeXAttr(path, name2);
    
    fs.setXAttr(path, name1, value1, EnumSet.of(XAttrSetFlag.CREATE));
    fs.setXAttr(path, name2, value2, EnumSet.of(XAttrSetFlag.CREATE));
    
    Map<String, byte[]> xattrs = fs.getXAttrs(path);
    Assert.assertEquals(xattrs.size(), 2);
    Assert.assertArrayEquals(value1, xattrs.get(name1));
    Assert.assertArrayEquals(value2, xattrs.get(name2));
  }

  @Test(timeout = 120000)
  public void testXAttrAcl() throws Exception {
    FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short) 0750));
    fs.setOwner(path, BRUCE.getUserName(), null);
    FileSystem fsAsBruce = createFileSystem(BRUCE);
    FileSystem fsAsDiana = createFileSystem(DIANA);
    fsAsBruce.setXAttr(path, name1, value1);

    Map<String, byte[]> xattrs;
    try {
      xattrs = fsAsDiana.getXAttrs(path);
      Assert.fail("Diana should not have read access to get xattrs");
    } catch (AccessControlException e) {
      // Ignore
    }

    // Give Diana read permissions to the path
    fsAsBruce.modifyAclEntries(path, Lists.newArrayList(
        aclEntry(ACCESS, USER, DIANA.getUserName(), READ)));
    xattrs = fsAsDiana.getXAttrs(path);
    Assert.assertArrayEquals(value1, xattrs.get(name1));

    try {
      fsAsDiana.removeXAttr(path, name1);
      Assert.fail("Diana should not have write access to remove xattrs");
    } catch (AccessControlException e) {
      // Ignore
    }

    try {
      fsAsDiana.setXAttr(path, name2, value2);
      Assert.fail("Diana should not have write access to set xattrs");
    } catch (AccessControlException e) {
      // Ignore
    }

    fsAsBruce.modifyAclEntries(path, Lists.newArrayList(
        aclEntry(ACCESS, USER, DIANA.getUserName(), ALL)));
    fsAsDiana.setXAttr(path, name2, value2);
    Assert.assertArrayEquals(value2, fsAsDiana.getXAttrs(path).get(name2));
    fsAsDiana.removeXAttr(path, name1);
    fsAsDiana.removeXAttr(path, name2);
  }
  
  @Test(timeout = 120000)
  public void testRawXAttrs() throws Exception {
    final UserGroupInformation user = UserGroupInformation.
      createUserForTesting("user", new String[] {"mygroup"});

    FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short) 0750));
    fs.setXAttr(rawPath, raw1, value1, EnumSet.of(XAttrSetFlag.CREATE,
        XAttrSetFlag.REPLACE));

    {
      // getXAttr
      final byte[] value = fs.getXAttr(rawPath, raw1);
      Assert.assertArrayEquals(value, value1);
    }

    {
      // getXAttrs
      final Map<String, byte[]> xattrs = fs.getXAttrs(rawPath);
      Assert.assertEquals(xattrs.size(), 1);
      Assert.assertArrayEquals(value1, xattrs.get(raw1));
      fs.removeXAttr(rawPath, raw1);
    }

    {
      // replace and re-get
      fs.setXAttr(rawPath, raw1, value1, EnumSet.of(XAttrSetFlag.CREATE));
      fs.setXAttr(rawPath, raw1, newValue1, EnumSet.of(XAttrSetFlag.CREATE,
          XAttrSetFlag.REPLACE));

      final Map<String,byte[]> xattrs = fs.getXAttrs(rawPath);
      Assert.assertEquals(xattrs.size(), 1);
      Assert.assertArrayEquals(newValue1, xattrs.get(raw1));

      fs.removeXAttr(rawPath, raw1);
    }

    {
      // listXAttrs on rawPath ensuring raw.* xattrs are returned
      fs.setXAttr(rawPath, raw1, value1, EnumSet.of(XAttrSetFlag.CREATE));
      fs.setXAttr(rawPath, raw2, value2, EnumSet.of(XAttrSetFlag.CREATE));

      final List<String> xattrNames = fs.listXAttrs(rawPath);
      assertTrue(xattrNames.contains(raw1));
      assertTrue(xattrNames.contains(raw2));
      assertTrue(xattrNames.size() == 2);
      fs.removeXAttr(rawPath, raw1);
      fs.removeXAttr(rawPath, raw2);
    }

    {
      // listXAttrs on non-rawPath ensuring no raw.* xattrs returned
      fs.setXAttr(rawPath, raw1, value1, EnumSet.of(XAttrSetFlag.CREATE));
      fs.setXAttr(rawPath, raw2, value2, EnumSet.of(XAttrSetFlag.CREATE));

      final List<String> xattrNames = fs.listXAttrs(path);
      assertTrue(xattrNames.size() == 0);
      fs.removeXAttr(rawPath, raw1);
      fs.removeXAttr(rawPath, raw2);
    }

    {
      /*
       * Test non-root user operations in the "raw.*" namespace.
       */
      user.doAs(new PrivilegedExceptionAction<Object>() {
        @Override
        public Object run() throws Exception {
          final FileSystem userFs = dfsCluster.getFileSystem();
          // Test that non-root can not set xattrs in the "raw.*" namespace
          try {
            // non-raw path
            userFs.setXAttr(path, raw1, value1);
            fail("setXAttr should have thrown");
          } catch (AccessControlException e) {
            // ignore
          }

          try {
            // raw path
            userFs.setXAttr(rawPath, raw1, value1);
            fail("setXAttr should have thrown");
          } catch (AccessControlException e) {
            // ignore
          }

          // Test that non-root can not do getXAttrs in the "raw.*" namespace
          try {
            // non-raw path
            userFs.getXAttrs(rawPath);
            fail("getXAttrs should have thrown");
          } catch (AccessControlException e) {
            // ignore
          }

          try {
            // raw path
            userFs.getXAttrs(path);
            fail("getXAttrs should have thrown");
          } catch (AccessControlException e) {
            // ignore
          }

          // Test that non-root can not do getXAttr in the "raw.*" namespace
          try {
            // non-raw path
            userFs.getXAttr(rawPath, raw1);
            fail("getXAttr should have thrown");
          } catch (AccessControlException e) {
            // ignore
          }

          try {
            // raw path
            userFs.getXAttr(path, raw1);
            fail("getXAttr should have thrown");
          } catch (AccessControlException e) {
            // ignore
          }
          return null;
        }
        });
    }

    {
      /*
       * Test that user who don'r have read access
       *  can not do getXAttr in the "raw.*" namespace
       */
      fs.setXAttr(rawPath, raw1, value1);
      user.doAs(new PrivilegedExceptionAction<Object>() {
          @Override
          public Object run() throws Exception {
            final FileSystem userFs = dfsCluster.getFileSystem();
            try {
              // raw path
              userFs.getXAttr(rawPath, raw1);
              fail("getXAttr should have thrown");
            } catch (AccessControlException e) {
              // ignore
            }

            try {
              // non-raw path
              userFs.getXAttr(path, raw1);
              fail("getXAttr should have thrown");
            } catch (AccessControlException e) {
              // ignore
            }

            /*
            * Test that user who have parent directory execute access
            *  can also not see raw.* xattrs returned from listXAttr
            */
            try {
              // non-raw path
              userFs.listXAttrs(path);
              fail("listXAttr should have thrown AccessControlException");
            } catch (AccessControlException ace) {
              // expected
            }

            try {
              // raw path
              userFs.listXAttrs(rawPath);
              fail("listXAttr should have thrown AccessControlException");
            } catch (AccessControlException ace) {
              // expected
            }
            return null;
          }
        });
      /*
        Test user who have read access can list xattrs in "raw.*" namespace
       */
      fs.setPermission(path, new FsPermission((short) 0751));
      final Path childDir = new Path(path, "child" + pathCount);
      FileSystem.mkdirs(fs, childDir, FsPermission.createImmutable((short)
          0704));
      final Path rawChildDir =
          new Path("/.reserved/raw" + childDir.toString());
      fs.setXAttr(rawChildDir, raw1, value1);
      user.doAs(new PrivilegedExceptionAction<Object>() {
        @Override
        public Object run() throws Exception {
          final FileSystem userFs = dfsCluster.getFileSystem();
          // raw path
          List<String> xattrs = userFs.listXAttrs(rawChildDir);
          assertEquals(1, xattrs.size());
          assertEquals(raw1, xattrs.get(0));
          return null;
        }
      });
      fs.removeXAttr(rawPath, raw1);
    }

    {
      /*
       * Tests that user who have read access are able to do getattr.
       */
      Path parentPath = new Path("/foo");
      fs.mkdirs(parentPath);
      fs.setOwner(parentPath, "user", "mygroup");
      // Set only execute permission for others on parent directory so that
      // any user can traverse down the directory.
      fs.setPermission(parentPath, new FsPermission("701"));
      Path childPath = new Path("/foo/bar");
      user.doAs(new PrivilegedExceptionAction<Object>() {
        @Override
        public Object run() throws Exception {
          final DistributedFileSystem dfs = dfsCluster.getFileSystem();
          DFSTestUtil.createFile(dfs, childPath, 1024, (short) 1, 0xFEED);
          dfs.setPermission(childPath, new FsPermission("740"));
          return null;
        }
      });
      Path rawChildPath =
          new Path("/.reserved/raw" + childPath.toString());
      fs.setXAttr(new Path("/.reserved/raw/foo/bar"), raw1, value1);
      user.doAs(new PrivilegedExceptionAction<Object>() {
        @Override
        public Object run() throws Exception {
          final DistributedFileSystem dfs = dfsCluster.getFileSystem();
          // Make sure user have access to raw xattr.
          byte[] xattr = dfs.getXAttr(rawChildPath, raw1);
          assertEquals(Arrays.toString(value1), Arrays.toString(xattr));
          return null;
        }
      });

      final UserGroupInformation fakeUser = UserGroupInformation
          .createUserForTesting("fakeUser", new String[] {"fakeGroup"});
      fakeUser.doAs(new PrivilegedExceptionAction<Object>() {
        @Override
        public Object run() throws Exception {
          final DistributedFileSystem dfs = dfsCluster.getFileSystem();
          try {
            // Make sure user who don't have read access to file can't access
            // raw xattr.
            dfs.getXAttr(path, raw1);
            fail("should have thrown AccessControlException");
          } catch (AccessControlException ace) {
            // expected
          }
          return null;
        }
      });
      // fs.removeXAttr(rawPath, raw1);
    }
  }

  /**
   * This tests the "unreadable by superuser" xattr which denies access to a
   * file for the superuser. See HDFS-6705 for details.
   */
  @Test(timeout = 120000)
  public void testUnreadableBySuperuserXAttr() throws Exception {
    // Run tests as superuser...
    doTestUnreadableBySuperuserXAttr(fs, true);

    // ...and again as non-superuser
    final UserGroupInformation user = UserGroupInformation.
        createUserForTesting("user", new String[] { "mygroup" });
    user.doAs(new PrivilegedExceptionAction<Object>() {
      @Override
      public Object run() throws Exception {
        final FileSystem userFs = dfsCluster.getFileSystem();
        doTestUnreadableBySuperuserXAttr(userFs, false);
        return null;
      }
    });
  }

  private void doTestUnreadableBySuperuserXAttr(FileSystem userFs,
      boolean expectOpenFailure) throws Exception {

    FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short) 0777));
    DFSTestUtil.createFile(userFs, filePath, 8192, (short) 1, 0xFEED);
    try {
      doTUBSXAInt(userFs, expectOpenFailure);
      // Deleting the file is allowed.
      userFs.delete(filePath, false);
    } finally {
      fs.delete(path, true);
    }
  }

  private void doTUBSXAInt(FileSystem userFs, boolean expectOpenFailure)
      throws Exception {

    // Test that xattr can't be set on a dir
    try {
      userFs.setXAttr(path, security1, null, EnumSet.of(XAttrSetFlag.CREATE));
    } catch (IOException e) {
      // WebHDFS throws IOException instead of RemoteException
      GenericTestUtils.assertExceptionContains("Can only set '" +
          SECURITY_XATTR_UNREADABLE_BY_SUPERUSER + "' on a file", e);
    }

    // Test that xattr can actually be set. Repeatedly.
    userFs.setXAttr(filePath, security1, null,
      EnumSet.of(XAttrSetFlag.CREATE));
    verifySecurityXAttrExists(userFs);
    userFs.setXAttr(filePath, security1, null, EnumSet.of(XAttrSetFlag.CREATE,
        XAttrSetFlag.REPLACE));
    verifySecurityXAttrExists(userFs);

    // Test that the xattr can't be deleted by anyone.
    try {
      userFs.removeXAttr(filePath, security1);
      Assert.fail("Removing security xattr should fail.");
    } catch (AccessControlException e) {
      GenericTestUtils.assertExceptionContains("The xattr '" +
          SECURITY_XATTR_UNREADABLE_BY_SUPERUSER + "' can not be deleted.", e);
    }

    // Test that xattr can be read.
    verifySecurityXAttrExists(userFs);

    // Test that a value can't be set for the xattr.
    try {
      userFs.setXAttr(filePath, security1,
          value1,EnumSet.of(XAttrSetFlag.REPLACE));
      fail("Should have thrown on attempt to set value");
    } catch (AccessControlException e) {
      GenericTestUtils.assertExceptionContains("Values are not allowed", e);
    }

    // Test that unreadable by superuser xattr appears in listXAttrs results
    // (for superuser and non-superuser)
    final List<String> xattrNames = userFs.listXAttrs(filePath);
    assertTrue(xattrNames.contains(security1));
    assertTrue(xattrNames.size() == 1);

    verifyFileAccess(userFs, expectOpenFailure);

    // Rename of the file is allowed by anyone.
    Path toPath = new Path(filePath.toString() + "x");
    userFs.rename(filePath, toPath);
    userFs.rename(toPath, filePath);
  }

  private void verifySecurityXAttrExists(FileSystem userFs) throws Exception {
    try {
      final Map<String, byte[]> xattrs = userFs.getXAttrs(filePath);
      Assert.assertEquals(1, xattrs.size());
      Assert.assertNotNull(xattrs.get(security1));
      Assert.assertArrayEquals("expected empty byte[] from getXAttr",
          new byte[0], userFs.getXAttr(filePath, security1));

    } catch (AccessControlException e) {
      fail("getXAttrs failed but expected it to succeed");
    }
  }

  private void verifyFileAccess(FileSystem userFs, boolean expectOpenFailure)
      throws Exception {
    // Test that a file with the xattr can or can't be opened.
    try {
      userFs.open(filePath).read();
      assertFalse("open succeeded but expected it to fail", expectOpenFailure);
    } catch (AccessControlException e) {
      assertTrue("open failed but expected it to succeed", expectOpenFailure);
    }
  }

  /**
   * Creates a FileSystem for the super-user.
   *
   * @return FileSystem for super-user
   * @throws Exception if creation fails
   */
  protected FileSystem createFileSystem() throws Exception {
    return dfsCluster.getFileSystem();
  }

  /**
   * Creates a FileSystem for a specific user.
   *
   * @param user UserGroupInformation specific user
   * @return FileSystem for specific user
   * @throws Exception if creation fails
   */
  protected FileSystem createFileSystem(UserGroupInformation user)
      throws Exception {
    return DFSTestUtil.getFileSystemAs(user, conf);
  }
  
  /**
   * Initializes all FileSystem instances used in the tests.
   *
   * @throws Exception if initialization fails
   */
  private void initFileSystem() throws Exception {
    fs = createFileSystem();
  }
  
  /**
   * Initialize the cluster, wait for it to become active, and get FileSystem
   * instances for our test users.
   *
   * @param format if true, format the NameNode and DataNodes before starting up
   * @throws Exception if any step fails
   */
  protected static void initCluster(boolean format) throws Exception {
    dfsCluster = new MiniDFSCluster.Builder(conf).numDataNodes(1).format(format)
      .build();
    dfsCluster.waitActive();
  }
  
  /**
   * Restart the cluster, optionally saving a new checkpoint.
   *
   * @param checkpoint boolean true to save a new checkpoint
   * @throws Exception if restart fails
   */
  protected static void restart(boolean checkpoint) throws Exception {
    NameNode nameNode = dfsCluster.getNameNode();
    if (checkpoint) {
      NameNodeAdapter.enterSafeMode(nameNode, false);
      NameNodeAdapter.saveNamespace(nameNode);
    }
    shutdown();
    initCluster(false);
  }
}
