Add AclBuilderTest
Code Review: https://codereview.appspot.com/35900047/
diff --git a/test/com/google/enterprise/adaptor/fs/AclBuilderTest.java b/test/com/google/enterprise/adaptor/fs/AclBuilderTest.java
new file mode 100644
index 0000000..1fb3414
--- /dev/null
+++ b/test/com/google/enterprise/adaptor/fs/AclBuilderTest.java
@@ -0,0 +1,435 @@
+// Copyright 2013 Google Inc. All Rights Reserved.
+//
+// Licensed 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 com.google.enterprise.adaptor.fs;
+
+import static com.google.enterprise.adaptor.fs.AclView.user;
+import static com.google.enterprise.adaptor.fs.AclView.group;
+import static com.google.enterprise.adaptor.fs.AclView.GenericPermission.*;
+
+import static org.junit.Assert.*;
+
+import static java.nio.file.attribute.AclEntryFlag.*;
+import static java.nio.file.attribute.AclEntryPermission.*;
+import static java.nio.file.attribute.AclEntryType.*;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.enterprise.adaptor.Acl;
+import com.google.enterprise.adaptor.Acl.InheritanceType;
+import com.google.enterprise.adaptor.DocId;
+import com.google.enterprise.adaptor.GroupPrincipal;
+import com.google.enterprise.adaptor.Principal;
+import com.google.enterprise.adaptor.UserPrincipal;
+
+import org.junit.*;
+import org.junit.rules.ExpectedException;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.AclEntry;
+import java.nio.file.attribute.AclFileAttributeView;
+import java.util.ArrayList;
+import java.util.Set;
+
+/**
+ * Test cases for {@link AclBuilder}.
+ */
+public class AclBuilderTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ private final Path doc = Paths.get("foo", "bar");
+ private final DocId inheritId = new DocId("foo");
+ private final Set<String> windowsAccounts = ImmutableSet.of(
+ "BUILTIN\\Administrators", "Everyone", "BUILTIN\\Users",
+ "BUILTIN\\Guest", "NT AUTHORITY\\INTERACTIVE",
+ "NT AUTHORITY\\Authenticated Users");
+ private final String builtinPrefix = "BUILTIN\\";
+ private final String namespace = "namespace";
+ private final Set<GroupPrincipal> emptyGroups = ImmutableSet.of();
+ private final AclFileAttributeView aclView = new AclView(
+ user("joe").type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT),
+ user("mary").type(ALLOW).perms(GENERIC_READ, GENERIC_WRITE)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT),
+ user("mike").type(DENY).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT),
+ group("EVERYONE").type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT),
+ group("sales").type(DENY).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT));
+
+ @Test
+ public void testConstructorNullPath() throws Exception {
+ thrown.expect(NullPointerException.class);
+ new AclBuilder(null, aclView, windowsAccounts, builtinPrefix, namespace);
+ }
+
+ @Test
+ public void testConstructorNullAclView() throws Exception {
+ thrown.expect(NullPointerException.class);
+ new AclBuilder(doc, null, windowsAccounts, builtinPrefix, namespace);
+ }
+
+ @Test
+ public void testConstructorNullAccounts() throws Exception {
+ thrown.expect(NullPointerException.class);
+ new AclBuilder(doc, aclView, null, builtinPrefix, namespace);
+ }
+
+ @Test
+ public void testConstructorNullPrefix() throws Exception {
+ thrown.expect(NullPointerException.class);
+ new AclBuilder(doc, aclView, windowsAccounts, null, namespace);
+ }
+
+ @Test
+ public void testConstructorNullNamespace() throws Exception {
+ thrown.expect(NullPointerException.class);
+ new AclBuilder(doc, aclView, windowsAccounts, builtinPrefix, null);
+ }
+
+ @Test
+ public void testGetAclForDirectory() throws Exception {
+ Acl acl = newBuilder(aclView).getAcl(inheritId, true, null);
+ Acl expected = expectedBuilder().build();
+ assertEquals(expected, acl);
+ }
+
+ @Test
+ public void testGetAclForFile() throws Exception {
+ Acl acl = newBuilder(aclView).getAcl(inheritId, false, null);
+ Acl expected = expectedBuilder()
+ .setInheritanceType(InheritanceType.LEAF_NODE)
+ .build();
+ assertEquals(expected, acl);
+ }
+
+ @Test
+ public void testGetShareAcl() throws Exception {
+ Acl acl = newBuilder(aclView).getShareAcl(inheritId);
+ Acl expected = expectedBuilder()
+ .setInheritanceType(InheritanceType.AND_BOTH_PERMIT)
+ .build();
+ assertEquals(expected, acl);
+ }
+
+ @Test
+ public void testGetInheritableByAllDescendentFoldersAcl() throws Exception {
+ String fragment = "allFoldersAcl";
+ Acl acl = newBuilder(aclView).getInheritableByAllDescendentFoldersAcl(
+ inheritId, fragment);
+ Acl expected = expectedBuilder(fragment).build();
+ assertEquals(expected, acl);
+ }
+
+ @Test
+ public void testGetInheritableByAllDescendentFilesAcl() throws Exception {
+ String fragment = "allFilesAcl";
+ Acl acl = newBuilder(aclView).getInheritableByAllDescendentFilesAcl(
+ inheritId, fragment);
+ Acl expected = expectedBuilder(fragment).build();
+ assertEquals(expected, acl);
+ }
+
+ @Test
+ public void testGetInheritableByChildFoldersOnlyAcl() throws Exception {
+ String fragment = "childFoldersAcl";
+ Acl acl = newBuilder(aclView).getInheritableByChildFoldersOnlyAcl(
+ inheritId, fragment);
+ Acl expected = expectedBuilder(fragment).build();
+ assertEquals(expected, acl);
+ }
+
+ @Test
+ public void testGetInheritableByChildFilesOnlyAcl() throws Exception {
+ String fragment = "childFilesAcl";
+ Acl acl = newBuilder(aclView).getInheritableByChildFilesOnlyAcl(
+ inheritId, fragment);
+ Acl expected = expectedBuilder(fragment).build();
+ assertEquals(expected, acl);
+ }
+
+ @Test
+ public void testFileInheritAcl() throws Exception {
+ // "mary" and "sales" are only inheritable by files, not directories.
+ AclFileAttributeView aclView = new AclView(
+ user("joe").type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT),
+ user("mary").type(ALLOW).perms(GENERIC_READ, GENERIC_WRITE)
+ .flags(FILE_INHERIT),
+ user("mike").type(DENY).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT),
+ group("EVERYONE").type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT),
+ group("sales").type(DENY).perms(GENERIC_READ)
+ .flags(FILE_INHERIT));
+ AclBuilder aclBuilder = newBuilder(aclView);
+
+ String fragment = "allFilesAcl";
+ Acl acl = aclBuilder.getInheritableByAllDescendentFilesAcl(inheritId,
+ fragment);
+ Acl expected = expectedBuilder(fragment).build();
+ assertEquals(expected, acl);
+
+ fragment = "childFilesAcl";
+ acl = aclBuilder.getInheritableByChildFilesOnlyAcl(inheritId, fragment);
+ expected = expectedBuilder(fragment).build();
+ assertEquals(expected, acl);
+
+ // The folder inherit ACLs should not include "mary" or "sales".
+ fragment = "allFoldersAcl";
+ acl = aclBuilder.getInheritableByAllDescendentFoldersAcl(inheritId,
+ fragment);
+ expected = expectedBuilder(fragment)
+ .setPermitUsers(users("joe")).setDenyGroups(emptyGroups).build();
+ assertEquals(expected, acl);
+
+ fragment = "childFoldersAcl";
+ acl = aclBuilder.getInheritableByAllDescendentFoldersAcl(inheritId,
+ fragment);
+ expected = expectedBuilder(fragment)
+ .setPermitUsers(users("joe")).setDenyGroups(emptyGroups).build();
+ assertEquals(expected, acl);
+ }
+
+ @Test
+ public void testFolderInheritAcl() throws Exception {
+ // "mary" and "sales" are only inheritable by directories, not files.
+ AclFileAttributeView aclView = new AclView(
+ user("joe").type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT),
+ user("mary").type(ALLOW).perms(GENERIC_READ, GENERIC_WRITE)
+ .flags(DIRECTORY_INHERIT),
+ user("mike").type(DENY).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT),
+ group("EVERYONE").type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT),
+ group("sales").type(DENY).perms(GENERIC_READ)
+ .flags(DIRECTORY_INHERIT));
+ AclBuilder aclBuilder = newBuilder(aclView);
+
+ String fragment = "allFoldersAcl";
+ Acl acl = aclBuilder.getInheritableByAllDescendentFoldersAcl(inheritId,
+ fragment);
+ Acl expected = expectedBuilder(fragment).build();
+ assertEquals(expected, acl);
+
+ fragment = "childFoldersAcl";
+ acl = aclBuilder.getInheritableByChildFoldersOnlyAcl(inheritId, fragment);
+ expected = expectedBuilder(fragment).build();
+ assertEquals(expected, acl);
+
+ // The file inherit ACLs should not include "mary" or "sales".
+ fragment = "allFilesAcl";
+ acl = aclBuilder.getInheritableByAllDescendentFilesAcl(inheritId,
+ fragment);
+ expected = expectedBuilder(fragment)
+ .setPermitUsers(users("joe")).setDenyGroups(emptyGroups).build();
+ assertEquals(expected, acl);
+
+ fragment = "childFilesAcl";
+ acl = aclBuilder.getInheritableByAllDescendentFilesAcl(inheritId,
+ fragment);
+ expected = expectedBuilder(fragment)
+ .setPermitUsers(users("joe")).setDenyGroups(emptyGroups).build();
+ assertEquals(expected, acl);
+ }
+
+ @Test
+ public void testNoPropagateFolderInheritAcl() throws Exception {
+ AclFileAttributeView aclView = new AclView(
+ user("joe").type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT),
+ user("mike").type(ALLOW).perms(GENERIC_READ)
+ .flags(DIRECTORY_INHERIT, NO_PROPAGATE_INHERIT),
+ user("mary").type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT));
+ AclBuilder aclBuilder = newBuilder(aclView);
+
+ Acl acl =
+ aclBuilder.getInheritableByAllDescendentFoldersAcl(inheritId, null);
+ Acl expected = emptyExpectedBuilder()
+ .setPermitUsers(users("joe", "mary")).build();
+ assertEquals(expected, acl);
+
+ acl = aclBuilder.getInheritableByChildFoldersOnlyAcl(inheritId, null);
+ expected = emptyExpectedBuilder()
+ .setPermitUsers(users("joe", "mike", "mary")).build();
+ assertEquals(expected, acl);
+ }
+
+ @Test
+ public void testNoPropagateFileInheritAcl() throws Exception {
+ AclFileAttributeView aclView = new AclView(
+ user("joe").type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT),
+ user("mike").type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, NO_PROPAGATE_INHERIT),
+ user("mary").type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT));
+ AclBuilder aclBuilder = newBuilder(aclView);
+
+ Acl acl =
+ aclBuilder.getInheritableByAllDescendentFilesAcl(inheritId, null);
+ Acl expected = emptyExpectedBuilder()
+ .setPermitUsers(users("joe", "mary")).build();
+ assertEquals(expected, acl);
+
+ acl = aclBuilder.getInheritableByChildFilesOnlyAcl(inheritId, null);
+ expected = emptyExpectedBuilder()
+ .setPermitUsers(users("joe", "mike", "mary")).build();
+ assertEquals(expected, acl);
+ }
+
+ @Test
+ public void testInheritOnlyAcl() throws Exception {
+ AclFileAttributeView aclView = new AclView(
+ user("joe").type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT),
+ user("mike").type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT, INHERIT_ONLY),
+ user("mary").type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT));
+ AclBuilder aclBuilder = newBuilder(aclView);
+
+ // This node's ACL should not include mike.
+ Acl acl = aclBuilder.getAcl(inheritId, true, null);
+ Acl expected = emptyExpectedBuilder()
+ .setPermitUsers(users("joe", "mary")).build();
+ assertEquals(expected, acl);
+
+ // However, all of its children should include mike.
+ expected = emptyExpectedBuilder()
+ .setPermitUsers(users("joe", "mike", "mary")).build();
+ acl = aclBuilder.getInheritableByAllDescendentFoldersAcl(inheritId, null);
+ assertEquals(expected, acl);
+ acl = aclBuilder.getInheritableByAllDescendentFilesAcl(inheritId, null);
+ assertEquals(expected, acl);
+ }
+
+ @Test
+ public void testInsufficientReadPerms() throws Exception {
+ AclFileAttributeView aclView = new AclView(
+ user("joe").type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT),
+ user("mike").type(ALLOW).perms(READ_DATA)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT));
+ AclBuilder aclBuilder = newBuilder(aclView);
+
+ // This node's ACLs should not include mike.
+ Acl expected = emptyExpectedBuilder()
+ .setPermitUsers(users("joe")).build();
+ Acl acl = aclBuilder.getAcl(inheritId, true, null);
+ assertEquals(expected, acl);
+ acl = aclBuilder.getInheritableByAllDescendentFoldersAcl(inheritId, null);
+ assertEquals(expected, acl);
+ acl = aclBuilder.getInheritableByAllDescendentFilesAcl(inheritId, null);
+ assertEquals(expected, acl);
+ }
+
+ @Test
+ public void testWindowsBuiltinUsers() throws Exception {
+ ArrayList<AclEntry> entries = Lists.newArrayList();
+ // Add all the permitted builtin users.
+ for (String builtin : windowsAccounts) {
+ entries.add(user(builtin).type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT).build());
+ }
+ String badBuiltin = builtinPrefix + "BACKUP";
+ // Now add a builtin user that should be excluded.
+ entries.add(user(badBuiltin).type(ALLOW).perms(GENERIC_READ)
+ .flags(FILE_INHERIT, DIRECTORY_INHERIT).build());
+
+ AclFileAttributeView aclView =
+ new AclView(entries.toArray(new AclEntry[0]));
+ AclBuilder aclBuilder = newBuilder(aclView);
+
+ // The permitted users should contain all of the acceptable builtins.
+ // But should not contain the bad builtin.
+ Acl expected = emptyExpectedBuilder()
+ .setPermitUsers(users(Iterables.toArray(windowsAccounts, String.class)))
+ .build();
+ Acl acl = aclBuilder.getAcl(inheritId, true, null);
+ assertEquals(expected, acl);
+ }
+
+ /** Returns an AclBuilder for the AclFileAttributeView. */
+ private AclBuilder newBuilder(AclFileAttributeView aclView) {
+ return new AclBuilder(doc, aclView, windowsAccounts, builtinPrefix,
+ namespace);
+ }
+
+ /**
+ * Returns an Acl.Builder representing the aclView field.
+ * The caller is expected to overwrite any of thes presets,
+ * then call build().
+ */
+ private Acl.Builder expectedBuilder() {
+ return expectedBuilder(null);
+ }
+
+ /**
+ * Returns an Acl.Builder representing the aclView field.
+ * The caller is expected to overwrite any of thes presets,
+ * then call build().
+ */
+ private Acl.Builder expectedBuilder(String fragment) {
+ return emptyExpectedBuilder(fragment)
+ .setPermitUsers(users("joe", "mary")).setDenyUsers(users("mike"))
+ .setPermitGroups(groups("EVERYONE")).setDenyGroups(groups("sales"));
+ }
+
+ /**
+ * Returns an Acl.Builder with no users or groups.
+ */
+ private Acl.Builder emptyExpectedBuilder() {
+ return emptyExpectedBuilder(null);
+ }
+
+ /**
+ * Returns an Acl.Builder with no users or groups.
+ */
+ private Acl.Builder emptyExpectedBuilder(String fragment) {
+ return new Acl.Builder().setInheritFrom(inheritId, fragment)
+ .setInheritanceType(InheritanceType.CHILD_OVERRIDES)
+ .setEverythingCaseInsensitive();
+ }
+
+ /**
+ * Returns a Set of UserPrincipals of the named users.
+ */
+ private Set<UserPrincipal> users(String... users) {
+ Set<UserPrincipal> principals = Sets.newHashSet();
+ for (String user : users) {
+ principals.add(new UserPrincipal(user, namespace));
+ }
+ return principals;
+ }
+
+ /**
+ * Returns a Set of GroupPrincipals of the named groups.
+ */
+ private Set<GroupPrincipal> groups(String... groups) {
+ Set<GroupPrincipal> principals = Sets.newHashSet();
+ for (String group : groups) {
+ principals.add(new GroupPrincipal(group, namespace));
+ }
+ return principals;
+ }
+}
diff --git a/test/com/google/enterprise/adaptor/fs/AclView.java b/test/com/google/enterprise/adaptor/fs/AclView.java
index 510a49e..233061e 100644
--- a/test/com/google/enterprise/adaptor/fs/AclView.java
+++ b/test/com/google/enterprise/adaptor/fs/AclView.java
@@ -14,6 +14,8 @@
package com.google.enterprise.adaptor.fs;
+import static java.nio.file.attribute.AclEntryPermission.*;
+
import java.nio.file.attribute.AclEntry;
import java.nio.file.attribute.AclEntryFlag;
import java.nio.file.attribute.AclEntryPermission;
@@ -24,7 +26,9 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.EnumSet;
import java.util.List;
+import java.util.Set;
/**
* This convenience class allows creation of an {@link AclFileAttributeView}
@@ -57,6 +61,27 @@
*/
class AclView extends SimpleAclFileAttributeView {
+ /** Compound permissions for easier specification. */
+ static enum GenericPermission {
+ GENERIC_READ(SYNCHRONIZE, READ_ACL, READ_DATA, READ_ATTRIBUTES,
+ READ_NAMED_ATTRS),
+ GENERIC_WRITE(SYNCHRONIZE, READ_ACL, WRITE_DATA, APPEND_DATA,
+ WRITE_ATTRIBUTES, WRITE_NAMED_ATTRS),
+ GENERIC_EXECUTE(SYNCHRONIZE, READ_ACL, READ_ATTRIBUTES, EXECUTE),
+ GENERIC_ALL(AclEntryPermission.values());
+
+ private final Set<AclEntryPermission> permissions;
+
+ GenericPermission(AclEntryPermission... permissions) {
+ this.permissions = Collections.unmodifiableSet(
+ EnumSet.copyOf(Arrays.asList(permissions)));
+ }
+
+ Set<AclEntryPermission> getPermissions() {
+ return permissions;
+ }
+ }
+
AclView() {
super(Collections.<AclEntry>emptyList());
}
@@ -112,6 +137,15 @@
return this;
}
+ AclEntryBuilder perms(GenericPermission... permissions) {
+ Set<AclEntryPermission> perms = EnumSet.noneOf(AclEntryPermission.class);
+ for (GenericPermission genericPerm : permissions) {
+ perms.addAll(genericPerm.getPermissions());
+ }
+ builder.setPermissions(perms);
+ return this;
+ }
+
AclEntryBuilder flags(AclEntryFlag... flags) {
builder.setFlags(flags);
return this;