// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.jdisc.application; import org.junit.Test; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * @author Simon Thoresen */ public class UriPatternTestCase { private static final List NO_GROUPS = Collections.emptyList(); @Test public void requireThatIllegalPatternsAreDetected() { assertIllegalPattern("scheme"); assertIllegalPattern("scheme://"); assertIllegalPattern("scheme://host"); assertIllegalPattern("scheme://host:0"); assertIllegalPattern("scheme://host:69"); assertIllegalPattern("scheme://host:-69"); assertIllegalPattern("scheme://host:6*/"); assertIllegalPattern("scheme://host:6*9/"); assertIllegalPattern("scheme://host:*9/"); } @Test public void requireThatNoPortImpliesWildcard() { assertEquals(new UriPattern("scheme://host/path"), new UriPattern("scheme://host:*/path")); } @Test public void requireThatPatternMatches() { // scheme matching UriPattern pattern = new UriPattern("bar://host:69/path"); assertNotMatch(pattern, "foobar://host:69/path"); assertMatch(pattern, "bar://host:69/path", NO_GROUPS); assertNotMatch(pattern, "barbaz://host:69/path"); pattern = new UriPattern("*://host:69/path"); assertMatch(pattern, "foobar://host:69/path", Arrays.asList("foobar")); assertMatch(pattern, "bar://host:69/path", Arrays.asList("bar")); assertMatch(pattern, "barbaz://host:69/path", Arrays.asList("barbaz")); pattern = new UriPattern("*bar://host:69/path"); assertMatch(pattern, "foobar://host:69/path", Arrays.asList("foo")); assertMatch(pattern, "bar://host:69/path", Arrays.asList("")); assertNotMatch(pattern, "barbaz://host:69/path"); pattern = new UriPattern("bar*://host:69/path"); assertNotMatch(pattern, "foobar://host:69/path"); assertMatch(pattern, "bar://host:69/path", Arrays.asList("")); assertMatch(pattern, "barbaz://host:69/path", Arrays.asList("baz")); // host matching pattern = new UriPattern("scheme://bar:69/path"); assertNotMatch(pattern, "scheme://foobar:69/path"); assertMatch(pattern, "scheme://bar:69/path", NO_GROUPS); assertNotMatch(pattern, "scheme://barbaz:69/path"); pattern = new UriPattern("scheme://*:69/path"); assertMatch(pattern, "scheme://foobar:69/path", Arrays.asList("foobar")); assertMatch(pattern, "scheme://bar:69/path", Arrays.asList("bar")); assertMatch(pattern, "scheme://barbaz:69/path", Arrays.asList("barbaz")); pattern = new UriPattern("scheme://*bar:69/path"); assertMatch(pattern, "scheme://foobar:69/path", Arrays.asList("foo")); assertMatch(pattern, "scheme://bar:69/path", Arrays.asList("")); assertNotMatch(pattern, "scheme://barbaz:69/path"); pattern = new UriPattern("scheme://bar*:69/path"); assertNotMatch(pattern, "scheme://foobar:69/path"); assertMatch(pattern, "scheme://bar:69/path", Arrays.asList("")); assertMatch(pattern, "scheme://barbaz:69/path", Arrays.asList("baz")); // port matching pattern = new UriPattern("scheme://host:69/path"); assertNotMatch(pattern, "scheme://host:669/path"); assertMatch(pattern, "scheme://host:69/path", NO_GROUPS); assertNotMatch(pattern, "scheme://host:699/path"); pattern = new UriPattern("scheme://host:*/path"); assertMatch(pattern, "scheme://host:669/path", Arrays.asList("669")); assertMatch(pattern, "scheme://host:69/path", Arrays.asList("69")); assertMatch(pattern, "scheme://host:699/path", Arrays.asList("699")); // path matching pattern = new UriPattern("scheme://host:69/"); assertMatch(pattern, "scheme://host:69/", NO_GROUPS); assertNotMatch(pattern, "scheme://host:69/foo"); pattern = new UriPattern("scheme://host:69/bar"); assertNotMatch(pattern, "scheme://host:69/foobar"); assertMatch(pattern, "scheme://host:69/bar", NO_GROUPS); assertNotMatch(pattern, "scheme://host:69/barbaz"); pattern = new UriPattern("scheme://host:69/*"); assertMatch(pattern, "scheme://host:69/", Arrays.asList("")); assertMatch(pattern, "scheme://host:69/foobar", Arrays.asList("foobar")); assertMatch(pattern, "scheme://host:69/bar", Arrays.asList("bar")); assertMatch(pattern, "scheme://host:69/barbaz", Arrays.asList("barbaz")); pattern = new UriPattern("scheme://host:69/*bar"); assertMatch(pattern, "scheme://host:69/foobar", Arrays.asList("foo")); assertMatch(pattern, "scheme://host:69/bar", Arrays.asList("")); assertNotMatch(pattern, "scheme://host:69/barbaz"); pattern = new UriPattern("scheme://host:69/bar*"); assertNotMatch(pattern, "scheme://host:69/foobar"); assertMatch(pattern, "scheme://host:69/bar", Arrays.asList("")); assertMatch(pattern, "scheme://host:69/barbaz", Arrays.asList("baz")); } @Test public void requireThatUriWithoutHostDoesNotThrowException() { String schemeOnly = "scheme:schemeSpecificPart"; String schemeAndPath = "scheme:/path"; String pathOnly = "path"; String pathOnlyWithSlash = "/path"; UriPattern pattern = new UriPattern("scheme://host/path"); assertNotMatch(pattern, schemeOnly); assertNotMatch(pattern, schemeAndPath); assertNotMatch(pattern, pathOnly); assertNotMatch(pattern, pathOnlyWithSlash); pattern = new UriPattern("scheme*://host*/path*"); assertNotMatch(pattern, schemeOnly); assertNotMatch(pattern, schemeAndPath); assertNotMatch(pattern, pathOnly); assertNotMatch(pattern, pathOnlyWithSlash); pattern = new UriPattern("*://*/*"); assertMatch(pattern, schemeOnly, Arrays.asList("scheme", "", "")); assertMatch(pattern, schemeAndPath, Arrays.asList("scheme", "", "path")); assertMatch(pattern, pathOnly, Arrays.asList("", "", "path")); assertMatch(pattern, pathOnlyWithSlash, Arrays.asList("", "", "path")); } @Test public void requireThatUriWithoutPathDoesNotThrowException() { UriPattern pattern = new UriPattern("scheme://host/path"); assertNotMatch(pattern, "scheme://host"); pattern = new UriPattern("scheme://host/*"); assertMatch(pattern, "scheme://host", Arrays.asList("")); } @Test public void requireThatOnlySchemeHostPortAndPathIsMatched() { UriPattern pattern = new UriPattern("scheme://host:69/path"); assertMatch(pattern, "scheme://host:69/path?foo", NO_GROUPS); assertMatch(pattern, "scheme://host:69/path?foo#bar", NO_GROUPS); } @Test public void requireThatHostSupportsWildcard() { UriPattern pattern = new UriPattern("scheme://*.host/path"); assertMatch(pattern, "scheme://a.host/path", Arrays.asList("a")); assertMatch(pattern, "scheme://a.b.host/path", Arrays.asList("a.b")); } @Test public void requireThatPrioritiesAreOrderedDescending() { assertCompareLt(new UriPattern("scheme://host:69/path", 1), new UriPattern("scheme://host:69/path", 0)); } @Test public void requireThatPriorityOrdersBeforeScheme() { assertCompareLt(new UriPattern("*://host:69/path", 1), new UriPattern("scheme://host:69/path", 0)); } @Test public void requireThatSchemesAreOrdered() { assertCompareLt("b://host:69/path", "a://host:69/path"); } @Test public void requireThatSchemeOrdersBeforeHost() { assertCompareLt("b://*:69/path", "a://host:69/path"); } @Test public void requireThatHostsAreOrdered() { assertCompareLt("scheme://b:69/path", "scheme://a:69/path"); } @Test public void requireThatHostOrdersBeforePath() { assertCompareLt("scheme://b:69/*", "scheme://a:69/path"); } @Test public void requireThatPortsAreOrdered() { for (int i = 1; i < 69; ++i) { assertCompareEq("scheme://host:" + i + "/path", "scheme://host:" + i + "/path"); assertCompareLt("scheme://host:" + (i + 1) + "/path", "scheme://host:" + i + "/path"); assertCompareLt("scheme://host:" + i + "/path", "scheme://host:*/path"); } } @Test public void requireThatPathsAreOrdered() { assertCompareLt("scheme://host:69/b", "scheme://host:69/a"); } @Test public void requireThatPathOrdersBeforePort() { assertCompareLt("scheme://host:*/b", "scheme://host:69/a"); } @Test public void requireThatEqualPatternsOrderEqual() { assertCompareEq("scheme://host:69/path", "scheme://host:69/path"); assertCompareEq("*://host:69/path", "*://host:69/path"); assertCompareEq("scheme://*:69/path", "scheme://*:69/path"); assertCompareEq("scheme://host:*/path", "scheme://host:*/path"); assertCompareEq("scheme://host:69/*", "scheme://host:69/*"); } @Test public void requireThatStrictPatternsOrderBeforeWildcards() { assertCompareLt("scheme://host:69/path", "*://host:69/path"); assertCompareLt("scheme://a:69/path", "scheme://*:69/path"); assertCompareLt("scheme://a:69/path", "scheme://*a:69/path"); assertCompareLt("scheme://*aa:69/path", "scheme://*a:69/path"); assertCompareLt("scheme://host:69/path", "scheme://host:*/path"); assertCompareLt("scheme://host:69/a", "scheme://host:69/*"); assertCompareLt("scheme://host:69/a", "scheme://host:69/a*"); assertCompareLt("scheme://host:69/aa*", "scheme://host:69/a*"); assertCompareLt("scheme://*:69/path", "*://host:69/path"); assertCompareLt("scheme://host:*/path", "scheme://*:69/path"); assertCompareLt("scheme://host:*/path", "scheme://host:69/*"); assertCompareLt("scheme://host:69/foo", "scheme://host:69/*"); assertCompareLt("scheme://host:69/foo/bar", "scheme://host:69/foo/*"); assertCompareLt("scheme://host:69/foo/bar/baz", "scheme://host:69/foo/bar/*"); } @Test public void requireThatLongPatternsOrderBeforeShort() { assertCompareLt("scheme://host:69/foo/bar", "scheme://host:69/foo"); assertCompareLt("scheme://host:69/foo/bar/baz", "scheme://host:69/foo/bar"); } private static void assertIllegalPattern(String uri) { try { new UriPattern(uri); fail(); } catch (IllegalArgumentException e) { // expected } } private static void assertCompareLt(String lhs, String rhs) { assertCompareLt(new UriPattern(lhs, 0), new UriPattern(rhs, 0)); } private static void assertCompareLt(UriPattern lhs, UriPattern rhs) { assertEquals(-1, compare(lhs, rhs)); } private static void assertCompareEq(String lhs, String rhs) { assertCompareEq(new UriPattern(lhs, 0), new UriPattern(rhs, 0)); } private static void assertCompareEq(UriPattern lhs, UriPattern rhs) { assertEquals(0, compare(lhs, rhs)); } private static int compare(UriPattern lhs, UriPattern rhs) { int lhsCmp = lhs.compareTo(rhs); int rhsCmp = rhs.compareTo(lhs); if (lhsCmp < 0) { assertTrue(rhsCmp > 0); return -1; } if (lhsCmp > 0) { assertTrue(rhsCmp < 0); return 1; } assertTrue(rhsCmp == 0); return 0; } private static void assertMatch(UriPattern pattern, String uri, List expected) { UriPattern.Match match = pattern.match(URI.create(uri)); assertNotNull(match); List actual = new ArrayList<>(match.groupCount()); for (int i = 0, len = match.groupCount(); i < len; ++i) { actual.add(match.group(i)); } assertEquals(expected, actual); } private static void assertNotMatch(UriPattern pattern, String uri) { assertNull(pattern.match(URI.create(uri))); } }