content: /*
   * 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.security.authorization;
  
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertFalse;
  import static org.junit.Assert.assertTrue;
  
  import com.google.common.collect.Lists;
  import com.google.common.testing.EqualsTester;
  import org.junit.Test;
  
  import java.util.Collections;
  import java.util.List;
  
  /**
   * Tests the {@link AccessControlList} class.
   */
  public class AccessControlListTest {
    private static final String OWNING_USER = "owning_user";
    private static final String OWNING_GROUP = "owning_group";
    private static final String NAMED_USER = "named_user";
    private static final String NAMED_GROUP = "named_group";
    private static final String NAMED_GROUP2 = "named_group2";
    private static final String OTHER_USER = "other_user";
    private static final String OTHER_GROUP = "other_group";
  
    /**
     * Tests the constructor contract.
     */
    @Test
    public void constructor() {
      AccessControlList acl = new AccessControlList();
      assertEquals("", acl.getOwningUser());
      assertEquals("", acl.getOwningGroup());
    }
  
    /**
     * Tests getting and setting owner and group.
     */
    @Test
    public void ownerGroup() {
      AccessControlList acl = new AccessControlList();
      acl.setOwningUser(OWNING_USER);
      acl.setOwningGroup(OWNING_GROUP);
      assertEquals(OWNING_USER, acl.getOwningUser());
      assertEquals(OWNING_GROUP, acl.getOwningGroup());
    }
  
    /**
     * Tests setting and getting permitted actions.
     */
    @Test
    public void actions() {
      AccessControlList acl = new AccessControlList();
      // owning user: rwx
      // owning group: -rx
      // other: ---
      // named user: rwx
      // named group: w-x
      acl.setOwningUser(OWNING_USER);
      acl.setOwningGroup(OWNING_GROUP);
      acl.setEntry(new AclEntry.Builder().setType(AclEntryType.OWNING_USER).setSubject(OWNING_USER)
          .addAction(AclAction.READ).addAction(AclAction.WRITE).addAction(AclAction.EXECUTE).build());
      acl.setEntry(new AclEntry.Builder().setType(AclEntryType.OWNING_GROUP).setSubject(OWNING_GROUP)
          .addAction(AclAction.READ).addAction(AclAction.EXECUTE).build());
      acl.setEntry(new AclEntry.Builder().setType(AclEntryType.OTHER).build());
      acl.setEntry(new AclEntry.Builder().setType(AclEntryType.NAMED_USER).setSubject(NAMED_USER)
          .addAction(AclAction.READ).addAction(AclAction.WRITE).addAction(AclAction.EXECUTE).build());
      acl.setEntry(new AclEntry.Builder().setType(AclEntryType.NAMED_GROUP).setSubject(NAMED_GROUP)
          .addAction(AclAction.WRITE).addAction(AclAction.EXECUTE).build());
      acl.updateMask();
      // Verify mode.
      // owning user
      assertTrue(checkMode(acl, OWNING_USER, Collections.emptyList(), Mode.Bits.ALL));
      // owning group
      assertTrue(checkMode(acl, OTHER_USER, Lists.newArrayList(OWNING_GROUP),
          Mode.Bits.READ_EXECUTE));
      assertFalse(checkMode(acl, OTHER_USER, Lists.newArrayList(OWNING_GROUP),
          Mode.Bits.WRITE));
      // other
      assertFalse(checkMode(acl, OTHER_USER, Collections.emptyList(), Mode.Bits.READ));
      assertFalse(checkMode(acl, OTHER_USER, Collections.emptyList(), Mode.Bits.WRITE));
      assertFalse(checkMode(acl, OTHER_USER, Collections.emptyList(), Mode.Bits.EXECUTE));
      // named user
      assertTrue(checkMode(acl, NAMED_USER, Collections.emptyList(), Mode.Bits.ALL));
      // named group
      assertTrue(checkMode(acl, OTHER_USER, Lists.newArrayList(NAMED_GROUP),
          Mode.Bits.WRITE_EXECUTE));
      assertFalse(checkMode(acl, OTHER_USER, Lists.newArrayList(NAMED_GROUP),
          Mode.Bits.READ));
    }
  
    private boolean checkMode(AccessControlList acl, String user, List<String> groups,
        Mode.Bits mode) {
      for (AclAction action : mode.toAclActionSet()) {
        if (!acl.checkPermission(user, groups, action)) {
          return false;
        }
      }
      return true;
    }
  
    /**
     * Tests {@link AccessControlList#getMode()}.
     */
    @Test
    public void getMode() {
      AccessControlList acl = new AccessControlList();
      assertEquals(0, acl.getMode());
      acl.setEntry(new AclEntry.Builder().setType(AclEntryType.OWNING_USER).setSubject(OWNING_USER)
          .addAction(AclAction.READ).build());
      acl.setEntry(new AclEntry.Builder().setType(AclEntryType.OWNING_GROUP).setSubject(OWNING_GROUP)
          .addAction(AclAction.WRITE).build());
      acl.setEntry(new AclEntry.Builder().setType(AclEntryType.OTHER)
          .addAction(AclAction.EXECUTE).build());
      assertEquals(new Mode(Mode.Bits.READ, Mode.Bits.WRITE, Mode.Bits.EXECUTE).toShort(),
          acl.getMode());
    }
  
    /**
     * Tests {@link AccessControlList#setMode(short)}.
     */
    @Test
    public void setMode() {
      AccessControlList acl = new AccessControlList();
      short mode = new Mode(Mode.Bits.EXECUTE, Mode.Bits.WRITE, Mode.Bits.READ).toShort();
      acl.setMode(mode);
      assertEquals(mode, acl.getMode());
    }
  
    private void setPermissions(AccessControlList acl) {
      // owning user: rwx
      // owning group: r-x
      // other: --x
      // named user: r-x
      // named group: r--
      // named group 2: -wx
      acl.setOwningUser(OWNING_USER);
      acl.setOwningGroup(OWNING_GROUP);
      acl.setEntry(new AclEntry.Builder().setType(AclEntryType.OWNING_USER).setSubject(OWNING_USER)
          .addAction(AclAction.READ).addAction(AclAction.WRITE).addAction(AclAction.EXECUTE).build());
      acl.setEntry(new AclEntry.Builder().setType(AclEntryType.OWNING_GROUP).setSubject(OWNING_GROUP)
          .addAction(AclAction.READ).addAction(AclAction.EXECUTE).build());
      acl.setEntry(new AclEntry.Builder().setType(AclEntryType.OTHER)
          .addAction(AclAction.EXECUTE).build());
      acl.setEntry(new AclEntry.Builder().setType(AclEntryType.NAMED_USER).setSubject(NAMED_USER)
          .addAction(AclAction.READ).addAction(AclAction.EXECUTE).build());
      acl.setEntry(new AclEntry.Builder().setType(AclEntryType.NAMED_GROUP).setSubject(NAMED_GROUP)
          .addAction(AclAction.READ).build());
      acl.setEntry(new AclEntry.Builder().setType(AclEntryType.NAMED_GROUP).setSubject(NAMED_GROUP2)
          .addAction(AclAction.WRITE).addAction(AclAction.EXECUTE).build());
      acl.updateMask();
    }
  
    /**
     * Tests {@link AccessControlList#checkPermission(String, List, AclAction)}.
     */
    @Test
    public void checkPermission() {
      AccessControlList acl = new AccessControlList();
      setPermissions(acl);
  
      assertTrue(checkMode(acl, OWNING_USER, Collections.emptyList(), Mode.Bits.ALL));
  
      assertTrue(checkMode(acl, NAMED_USER, Collections.emptyList(), Mode.Bits.READ_EXECUTE));
      assertFalse(checkMode(acl, NAMED_USER, Collections.emptyList(), Mode.Bits.WRITE));
  
      assertTrue(checkMode(acl, OTHER_USER, Lists.newArrayList(OWNING_GROUP),
          Mode.Bits.READ_EXECUTE));
      assertFalse(checkMode(acl, OTHER_USER, Lists.newArrayList(OWNING_GROUP),
          Mode.Bits.WRITE));
  
      assertTrue(checkMode(acl, OTHER_USER, Lists.newArrayList(NAMED_GROUP), Mode.Bits.READ));
      assertFalse(checkMode(acl, OTHER_USER, Lists.newArrayList(NAMED_GROUP),
          Mode.Bits.WRITE));
      assertFalse(checkMode(acl, OTHER_USER, Lists.newArrayList(NAMED_GROUP),
          Mode.Bits.EXECUTE));
  
      assertTrue(checkMode(acl, OTHER_USER, Lists.newArrayList(OTHER_GROUP),
          Mode.Bits.EXECUTE));
      assertFalse(checkMode(acl, OTHER_USER, Lists.newArrayList(OTHER_GROUP),
          Mode.Bits.READ));
      assertFalse(checkMode(acl, OTHER_USER, Lists.newArrayList(OTHER_GROUP),
          Mode.Bits.WRITE));
    }
  
    private void assertMode(Mode.Bits expected, AccessControlList acl, String user,
        List<String> groups) {
      assertEquals(expected, acl.getPermission(user, groups).toModeBits());
    }
  
    /**
     * Tests {@link AccessControlList#getPermission(String, List)}.
     */
    @Test
    public void getPermission() {
      AccessControlList acl = new AccessControlList();
      setPermissions(acl);
  
      assertMode(Mode.Bits.ALL, acl, OWNING_USER, Collections.emptyList());
      assertMode(Mode.Bits.READ_EXECUTE, acl, NAMED_USER, Collections.emptyList());
      assertMode(Mode.Bits.READ_EXECUTE, acl, OTHER_USER, Lists.newArrayList(OWNING_GROUP));
      assertMode(Mode.Bits.READ, acl, OTHER_USER, Lists.newArrayList(NAMED_GROUP));
      assertMode(Mode.Bits.WRITE_EXECUTE, acl, OTHER_USER, Lists.newArrayList(NAMED_GROUP2));
      assertMode(Mode.Bits.ALL, acl, OTHER_USER, Lists.newArrayList(NAMED_GROUP, NAMED_GROUP2));
      assertMode(Mode.Bits.EXECUTE, acl, OTHER_USER, Collections.emptyList());
      assertMode(Mode.Bits.EXECUTE, acl, OTHER_USER, Lists.newArrayList(OTHER_GROUP));
    }
  
    /**
     * Basic equality test to make sure that subclasses are only equal to their respective types.
     */
    @Test
    public void checkEquals() {
      AccessControlList a1 = new AccessControlList();
      a1.setOwningUser("test1");
      DefaultAccessControlList a2 = new DefaultAccessControlList();
      a2.setOwningUser("test2");
      new EqualsTester()
          .addEqualityGroup(new DefaultAccessControlList(), new DefaultAccessControlList())
          .addEqualityGroup(new AccessControlList(), new AccessControlList())
          .addEqualityGroup(a1)
          .addEqualityGroup(a2)
          .testEquals();
    }
  }
  