blob: 3e645e1bc544f867557d1f5e8e23930cde8f56b0 [file] [log] [blame]
/*
* 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.jackrabbit.oak.security.authorization.restriction;
import java.util.HashMap;
import java.util.Map;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class GlobPatternTest {
private static void assertMatch(GlobPattern gp, String testPath, Boolean expectedResult) {
Boolean match = Boolean.valueOf(gp.matches(testPath));
assertEquals("Pattern : " + gp + "; TestPath : " + testPath, expectedResult, match);
}
@Test
public void testMatchesWildcardAll() {
Map<String,Boolean> tests = new HashMap<String,Boolean>();
// restriction "*" matches /foo, all siblings of foo and foo's and the siblings' descendants
GlobPattern gp = GlobPattern.create("/a/b/c", "*");
// matching
tests.put("/a/b/c", true); // foo itself
tests.put("/a/b/c/d", true); // child of foo
tests.put("/a/b/c/d/e", true); // child of foo
tests.put("/a/b/c/d/e/f", true); // child of foo
tests.put("/a/b/cde", true); // sibling
tests.put("/a/b/cde/e/f", true); // child of the sibling
// not-matching
tests.put("/", false);
tests.put("/a", false);
tests.put("/b/c", false);
for (String testPath : tests.keySet()) {
assertMatch(gp, testPath, tests.get(testPath));
}
// restriction "*cat" matches all siblings and descendants of /foo that have a name ending with cat
gp = GlobPattern.create("/a/b/c", "*e");
tests = new HashMap<String,Boolean>();
// matching
tests.put("/a/b/c/e", true); // descendant with name segment 'e'
tests.put("/a/b/c/d/e", true); // descendant with name segment 'e'
tests.put("/a/b/c/gge", true); // descendant with name segment ending with 'e'
tests.put("/a/b/c/d/gge", true); // descendant with name segment ending with 'e'
tests.put("/a/b/ce", true); // sibling whose name ends with 'e'
tests.put("/a/b/chee", true); // sibling whose name ends with 'e'
tests.put("/a/b/cd/e", true); // descendant of sibling named 'e'
tests.put("/a/b/cd/f/e", true); // descendant of sibling named 'e'
tests.put("/a/b/cd/e", true); // descendant of sibling with name ending with 'e'
tests.put("/a/b/cd/f/e", true); // descendant of sibling with name ending with 'e'
// not-matching
tests.put("/", false);
tests.put("/a", false);
tests.put("/b/c", false);
tests.put("/a/b/c", false);
tests.put("/a/b/c/d", false);
tests.put("/a/b/c/d/e/f", false);
tests.put("/a/b/c/d/f/e/f", false);
tests.put("/a/b/c/d/f/efg", false);
tests.put("/a/b/c/d/f/f", false);
tests.put("/a/b/c/e/f", false);
tests.put("/a/b/ce/", false);
tests.put("/a/b/ceg", false);
for (String testPath : tests.keySet()) {
assertMatch(gp, testPath, tests.get(testPath));
}
// restriction "*/cat" matches all descendants of /foo and foo's siblings that have a name segment "cat"
gp = GlobPattern.create("/a/b/c", "*/e");
tests = new HashMap<String,Boolean>();
// matching
tests.put("/a/b/c/e", true); // descendant with name segment 'e'
tests.put("/a/b/c/d/e", true); // descendant with name segment 'e'
tests.put("/a/b/cd/e", true); // descendant of sibling named 'e'
tests.put("/a/b/cd/f/e", true); // descendant of sibling named 'e'
// not-matching
tests.put("/", false);
tests.put("/a", false);
tests.put("/b/c", false);
tests.put("/a/b/c", false);
tests.put("/a/b/c/d", false);
tests.put("/a/b/c/d/e/f", false);
tests.put("/a/b/c/d/f/e/f", false);
tests.put("/a/b/c/d/f/efg", false);
tests.put("/a/b/c/d/f/f", false);
tests.put("/a/b/c/e/f", false);
tests.put("/a/b/ce/", false);
for (String testPath : tests.keySet()) {
assertMatch(gp, testPath, tests.get(testPath));
}
// matches target path '/a/b/c/e', all siblings whose name starts with e
// and child nodes of either.
gp = GlobPattern.create("/a/b/c/e", "*");
tests = new HashMap<String,Boolean>();
// matching
tests.put("/a/b/c/e/f/g/h", true);
tests.put("/a/b/c/e/d/e/f", true);
tests.put("/a/b/c/e/d/e/f", true);
tests.put("/a/b/c/e", true);
tests.put("/a/b/c/e/", true);
tests.put("/a/b/c/ef", true);
tests.put("/a/b/c/ef/g", true);
// not-matching
tests.put("/a/b/ce/f/g/h", false);
tests.put("/a/b/ce/d/e/f", false);
tests.put("/a/b/c", false);
tests.put("/a/b/c/d", false);
tests.put("/a/b/c/d/e/f", false);
tests.put("/a/b/c/d/f/f", false);
tests.put("/a/b/c/d/f/e/f", false);
tests.put("/a/b/cee/d/e/f", false);
for (String testPath : tests.keySet()) {
assertMatch(gp, testPath, tests.get(testPath));
}
// all descendants of '/a/b/c/e'
gp = GlobPattern.create("/a/b/c/e", "/*");
tests = new HashMap<String,Boolean>();
// matching
tests.put("/a/b/c/e/f/g/h", true);
tests.put("/a/b/c/e/d/e/f", true);
// not-matching
tests.put("/a/b/c/e", false); // not matching node path
tests.put("/a/b/c/e/", false); // not matching node path + /
tests.put("/a/b/c/ef", false); // not matching siblings of node path
tests.put("/a/b/ce/f/g/h", false);
tests.put("/a/b/ce/d/e/f", false);
tests.put("/a/b/c", false);
tests.put("/a/b/c/d", false);
tests.put("/a/b/c/d/e", false);
tests.put("/a/b/c/d/e/f", false);
tests.put("/a/b/c/d/f/f", false);
tests.put("/a/b/c/d/f/e/f", false);
tests.put("/a/b/cee/d/e/f", false);
for (String testPath : tests.keySet()) {
assertMatch(gp, testPath, tests.get(testPath));
}
// all descendants of '/a/b/ce'
gp = GlobPattern.create("/a/b/c", "e/*");
tests = new HashMap<String,Boolean>();
// not-matching
tests.put("/a/b/ce/f/g/h", true);
tests.put("/a/b/ce/d/e/f", true);
// not-matching
tests.put("/a/b/c", false);
tests.put("/a/b/ce", false);
tests.put("/a/b/c/d", false);
tests.put("/a/b/c/d/e", false);
tests.put("/a/b/c/d/e/f", false);
tests.put("/a/b/c/d/f/f", false);
tests.put("/a/b/c/d/f/e/f", false);
tests.put("/a/b/cee/d/e/f", false);
tests.put("/a/b/ce/", false); // missing * after ce/
for (String testPath : tests.keySet()) {
assertMatch(gp, testPath, tests.get(testPath));
}
// all descendants of '/'
gp = GlobPattern.create("/", "*");
tests = new HashMap<String,Boolean>();
// matching
tests.put("/a", true);
tests.put("/b/", true);
tests.put("/c/d", true);
tests.put("/a/b/ce/", true);
tests.put("/a/b/ce/f/g/h", true);
tests.put("/a/b/ce/d/e/f", true);
// not-matching
tests.put("/", false);
for (String testPath : tests.keySet()) {
assertMatch(gp, testPath, tests.get(testPath));
}
// restriction "*cat/*" matches all siblings and descendants of /foo that have an intermediate segment ending with 'cat'
gp = GlobPattern.create("/a/b/c", "*e/*");
tests = new HashMap<String,Boolean>();
// matching
tests.put("/a/b/ceeeeeee/f/g/h", true);
tests.put("/a/b/cde/d/e/f", true);
tests.put("/a/b/c/d/e/f", true);
tests.put("/a/b/ced/d/e/f", true);
// not-matching
tests.put("/a/b/cde", false); // sibling ending with e
tests.put("/a/b/ce/", false); // ignore trailing / in test path
tests.put("/a/b/c/d/e/", false); // ignore trailing / in test path
tests.put("/a/b/c/d", false); // missing *e/*
tests.put("/a/b/c/d/e", false); // missing /*
tests.put("/a/b/c/d/f/f", false); // missing *e
tests.put("/a/b/c/ed/f/f", false); // missing e/
for (String testPath : tests.keySet()) {
assertMatch(gp, testPath, tests.get(testPath));
}
// restriction /*cat/* matches all descendants of /foo that have an intermediate segment ending with 'cat'
gp = GlobPattern.create("/a/b/c", "/*e/*");
tests = new HashMap<String,Boolean>();
// matching
tests.put("/a/b/c/d/e/f", true);
tests.put("/a/b/c/de/f", true);
// not-matching
tests.put("/a/b/cde", false); // sibling ending with e
tests.put("/a/b/ced/d/e/f", false);// sibling containing intermediate segment
tests.put("/a/b/cde/d/e/f", false);// sibling containing intermediate segment
tests.put("/a/b/ce/", false); // ignore trailing / in test path
tests.put("/a/b/c/d/e/", false); // ignore trailing / in test path
tests.put("/a/b/c/d/e", false); // no intermediate segment
tests.put("/a/b/c/d", false); // missing *e/*
tests.put("/a/b/c/d/e", false); // missing /*
tests.put("/a/b/c/d/f/f", false); // missing *e
tests.put("/a/b/c/ed/f/f", false); // missing e/
for (String testPath : tests.keySet()) {
assertMatch(gp, testPath, tests.get(testPath));
}
// restriction /*cat matches all children of /a/b/c whose path ends with "cat"
gp = GlobPattern.create("/a/b/c", "/*cat");
tests = new HashMap<String,Boolean>();
// matching
tests.put("/a/b/c/cat", true);
tests.put("/a/b/c/acat", true);
tests.put("/a/b/c/f/cat", true);
tests.put("/a/b/c/f/acat", true);
// not-matching
tests.put("/a/b/c/d", false);
tests.put("/a/b/c/d/cat/e", false); // cat only intermediate segment
tests.put("/a/b/c/d/acat/e", false); // cat only intermediate segment
tests.put("/a/b/c/d/cata/e", false); // cat only intermediate segment
tests.put("/a/b/c/d/cate", false);
tests.put("/a/b/cat", false); // siblings do no match
tests.put("/a/b/cat/ed/f/f", false); // ... nor do siblings' children
tests.put("/a/b/ced/cat", false); // ... nor do siblings' children
for (String testPath : tests.keySet()) {
assertMatch(gp, testPath, tests.get(testPath));
}
// restriction /*/cat matches all non-direct descendants of /foo named "cat"
gp = GlobPattern.create("/a/b/c", "/*/cat");
tests = new HashMap<String,Boolean>();
// matching
tests.put("/a/b/c/a/cat", true);
tests.put("/a/b/c/d/e/f/cat", true);
// not-matching
tests.put("/a/b/c/cat", false);
tests.put("/a/b/c/cate", false);
tests.put("/a/b/c/acat", false);
tests.put("/a/b/c/cat/d", false);
tests.put("/a/b/c/d/acat", false);
tests.put("/a/b/c/d/cate", false);
tests.put("/a/b/c/d/cat/e", false); // cat only intermediate segment
tests.put("/a/b/c/d/acat/e", false); // cat only intermediate segment
tests.put("/a/b/c/d/cata/e", false); // cat only intermediate segment
tests.put("/a/b/cat", false); // siblings do no match
tests.put("/a/b/cat/ed/f/f", false); // ... nor do siblings' children
tests.put("/a/b/ced/cat", false); // ... nor do siblings' children
tests.put("/a/b/ced/f/cat", false); // ... nor do siblings' children
for (String testPath : tests.keySet()) {
assertMatch(gp, testPath, tests.get(testPath));
}
// restriction /cat* matches all descendant paths of /foo that have the
// direct foo-descendant segment starting with "cat"
gp = GlobPattern.create("/a/b/c", "/cat*");
tests = new HashMap<String,Boolean>();
// matching
tests.put("/a/b/c/cat", true);
tests.put("/a/b/c/cats", true);
tests.put("/a/b/c/cat/s", true);
tests.put("/a/b/c/cats/d/e/f", true);
// not-matching
tests.put("/a/b/c/d/cat", false);
tests.put("/a/b/c/d/cats", false);
tests.put("/a/b/c/d/e/cat", false);
tests.put("/a/b/c/d/e/cats", false);
tests.put("/a/b/c/acat", false);
tests.put("/a/b/c/d/acat", false);
tests.put("/a/b/c/d/cat/e", false);
tests.put("/a/b/c/d/acat/e", false);
tests.put("/a/b/c/d/cata/e", false);
tests.put("/a/b/cat", false); // siblings do no match
tests.put("/a/b/cat/ed/f/f", false); // ... nor do siblings' children
tests.put("/a/b/ced/cat", false); // ... nor do siblings' children
tests.put("/a/b/ced/f/cat", false); // ... nor do siblings' children
for (String testPath : tests.keySet()) {
assertMatch(gp, testPath, tests.get(testPath));
}
}
@Test
public void testEmptyRestriction() {
GlobPattern gp = GlobPattern.create("/", "");
Map<String,Boolean> tests = new HashMap<String,Boolean>();
tests.put("/", true);
tests.put("/a/b/c/d", false);
tests.put("/a/b/c/d/e", false);
tests.put("/a/b/c/d/e/f", false);
tests.put("/a/b/c", false);
tests.put("/a", false);
tests.put("/a/b/cde", false);
for (String toTest : tests.keySet()) {
assertTrue(gp + " : " + toTest, tests.get(toTest) == gp.matches(toTest));
}
gp = GlobPattern.create("/a/b/c", "");
tests = new HashMap<String,Boolean>();
tests.put("/a/b/c", true);
tests.put("/a/b/c/d", false);
tests.put("/a/b/c/d/e", false);
tests.put("/a/b/c/d/e/f", false);
tests.put("/", false);
tests.put("/a", false);
tests.put("/a/b/cde", false);
for (String toTest : tests.keySet()) {
assertTrue(gp + " : " + toTest, tests.get(toTest) == gp.matches(toTest));
}
}
@Test
public void testPathRestriction() {
GlobPattern gp = GlobPattern.create("/a/b/c", "d");
Map<String,Boolean> tests = new HashMap<String,Boolean>();
tests.put("/", false);
tests.put("/a", false);
tests.put("/a/b/c", false);
tests.put("/a/b/c/d", false);
tests.put("/a/b/c/d/e/f", false);
tests.put("/a/b/cd", true);
tests.put("/a/b/cd/e", true);
tests.put("/a/b/cd/e/f", true);
tests.put("/a/b/cde", false);
for (String toTest : tests.keySet()) {
assertTrue(gp + " : " + toTest, tests.get(toTest) == gp.matches(toTest));
}
gp = GlobPattern.create("/a/b/c", "/d");
tests = new HashMap<String,Boolean>();
tests.put("/", false);
tests.put("/a", false);
tests.put("/a/b/c", false);
tests.put("/a/b/c/d", true);
tests.put("/a/b/c/d/e/f", true);
tests.put("/a/b/cd", false);
tests.put("/a/b/cd/e", false);
tests.put("/a/b/cd/e/f", false);
tests.put("/a/b/cde", false);
for (String toTest : tests.keySet()) {
assertTrue(gp + " : " + toTest, tests.get(toTest) == gp.matches(toTest));
}
}
@Test
public void testMaxOccurrences() {
GlobPattern gp = GlobPattern.create("/", "1*/2*/3*/4*/5*/6*/7*/8*/9*/10*/11*/12*/13*/14*/15*/16*/17*/18*/19*/20*/21*");
try {
gp.matches("/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21");
fail();
} catch (IllegalArgumentException e) {
// success
};
try {
gp.matches("/11/22/33/44/55/66/77/88/99/100/111/122/133/144/155/166/177/188/199/200/211");
fail();
} catch (IllegalArgumentException e) {
// success
};
}
@Test
public void testMatches() {
assertFalse(GlobPattern.create("/a/b/c/d", "/*").matches());
}
@Test
public void testHashCode() {
GlobPattern pattern = GlobPattern.create("/a/b/c/d", "/*");
assertEquals(Objects.hashCode("/a/b/c/d", "/*"), pattern.hashCode());
}
@Test
public void testEquals() {
GlobPattern pattern = GlobPattern.create("/a/b/c/d", "/*");
assertEquals(pattern, pattern);
assertEquals(pattern, GlobPattern.create("/a/b/c/d", "/*"));
}
@Test
public void testNotEquals() {
GlobPattern pattern = GlobPattern.create("/a/b/c/d", "/*");
assertNotEquals(pattern, GlobPattern.create("/a/b/c", "/*"));
assertNotEquals(pattern, GlobPattern.create("/a/b/c/d", "*"));
assertNotEquals(pattern, new PrefixPattern(ImmutableSet.of("/a/b/c", "/*")));
}
}