/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* 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.alibaba.citrus.util.regex;
import static com.alibaba.citrus.util.ArrayUtil.*;
import static org.junit.Assert.*;
import java.text.MessageFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.Test;
public class WildcardCompilerTests {
@Test
public void pathNameWildcard() throws Exception {
Pattern pattern = PathNameWildcardCompiler.compilePathName("/ab?/def/**/ghi/*.jsp");
assertTrue(contains("/abc/def/ghi/test.jsp", pattern, "c", "", "test"));
assertTrue(contains("/abd/def/xxx/ghi/test.jsp", pattern, "d", "xxx", "test"));
assertTrue(contains("/abe/def/xxx/yyy/ghi/test.jsp", pattern, "e", "xxx/yyy", "test"));
assertTrue(contains("/abf/def/ghi/.jsp", pattern, "f", "", ""));
assertTrue(contains("/abg/def/ghi/.jsp", pattern, "g", "", ""));
assertFalse(contains("/ab/def/ghi/test.jsp", pattern));
assertFalse(contains("/abcd/def/ghi/test.jsp", pattern));
assertFalse(contains("/abc/def/xxxghi/test.jsp", pattern));
assertFalse(contains("/abc/defxxx/ghi/test.jsp", pattern));
assertFalse(contains("/abc/def/ghi/jsp", pattern));
pattern = PathNameWildcardCompiler.compilePathName("/xxx/yyy/**");
assertTrue(contains("/xxx/yyy/", pattern, ""));
assertTrue(contains("/xxx/yyy/zzz", pattern, "zzz"));
assertTrue(contains("/xxx/yyy/zzz/aaa", pattern, "zzz/aaa"));
assertTrue(contains("/xxx/yyy/zzz/aaa/", pattern, "zzz/aaa/"));
assertFalse(contains("/xxx/yyy", pattern));
assertFalse(contains("xxx/yyy", pattern));
assertFalse(contains("xxx/yyy/zzz", pattern));
assertFalse(contains("xxx/yyy/zzz/aaa", pattern));
assertFalse(contains("xxx/yyy/zzz/aaa/", pattern));
pattern = PathNameWildcardCompiler.compilePathName("/xxx/yyy");
assertTrue(contains("/xxx/yyy", pattern));
assertFalse(contains("/xxx/yyyzzz", pattern));
pattern = PathNameWildcardCompiler.compilePathName("/xxx/yyy*");
assertTrue(contains("/xxx/yyy", pattern, ""));
assertTrue(contains("/xxx/yyyzzz", pattern, "zzz"));
// 以?结束
pattern = PathNameWildcardCompiler.compilePathName("/xxx/yyy?");
assertTrue(contains("/xxx/yyyz", pattern, "z"));
assertTrue(contains("/xxx/yyyz/", pattern, "z"));
assertFalse(contains("/xxx/yyyzz", pattern));
// 以?开始
pattern = PathNameWildcardCompiler.compilePathName("?xxx/yyy");
assertTrue(contains("/zxxx/yyy", pattern, "z"));
assertFalse(contains("/zzxxx/yyy", pattern));
// 特殊处理
pattern = PathNameWildcardCompiler.compilePathName("/");
assertTrue(contains("", pattern));
assertTrue(contains("/xxx/yyy", pattern));
pattern = PathNameWildcardCompiler.compilePathName("");
assertTrue(contains("", pattern));
assertTrue(contains("/xxx/yyy", pattern));
}
@Test
public void pathNameRelevant() {
assertEquals(0, PathNameWildcardCompiler.getPathNameRelevancy(null));
assertEquals(0, PathNameWildcardCompiler.getPathNameRelevancy(" "));
assertEquals(0, PathNameWildcardCompiler.getPathNameRelevancy(""));
assertEquals(0, PathNameWildcardCompiler.getPathNameRelevancy("/*/**"));
assertEquals(1, PathNameWildcardCompiler.getPathNameRelevancy("/a?/**"));
assertEquals(3, PathNameWildcardCompiler.getPathNameRelevancy("/a?/**/bc"));
}
@Test
public void classNameWildcard() throws Exception {
Pattern pattern = ClassNameWildcardCompiler.compileClassName("ab?.def.**.ghi.*.jsp");
assertTrue(contains("abc.def.ghi.test.jsp", pattern, "c", "", "test"));
assertTrue(contains("abd.def.xxx.ghi.test.jsp", pattern, "d", "xxx", "test"));
assertTrue(contains("abe.def.xxx.yyy.ghi.test.jsp", pattern, "e", "xxx.yyy", "test"));
assertFalse(contains("abf.def.ghi..jsp", pattern));
assertFalse(contains("abg.def.ghi..jsp", pattern));
assertFalse(contains("ab.def.ghi.test.jsp", pattern));
assertFalse(contains("abcd.def.ghi.test.jsp", pattern));
assertFalse(contains("abc.def.xxxghi.test.jsp", pattern));
assertFalse(contains("abc.defxxx.ghi.test.jsp", pattern));
assertFalse(contains("abc.def.ghi.jsp", pattern));
pattern = ClassNameWildcardCompiler.compileClassName("xxx.yyy.**");
assertTrue(contains("xxx.yyy.", pattern, ""));
assertTrue(contains("xxx.yyy.zzz", pattern, "zzz"));
assertTrue(contains("xxx.yyy.zzz.aaa", pattern, "zzz.aaa"));
assertTrue(contains("xxx.yyy.zzz.aaa.", pattern, "zzz.aaa."));
assertFalse(contains("xxx.yyy", pattern));
assertFalse(contains("xxx.yyy", pattern));
pattern = ClassNameWildcardCompiler.compileClassName("xxx.yyy");
assertTrue(contains("xxx.yyy", pattern));
assertFalse(contains("xxx.yyyzzz", pattern));
pattern = ClassNameWildcardCompiler.compileClassName("xxx.yyy*");
assertTrue(contains("xxx.yyy", pattern, ""));
assertTrue(contains("xxx.yyyzzz", pattern, "zzz"));
// 以?结尾
pattern = ClassNameWildcardCompiler.compileClassName("xxx.yyy?");
assertTrue(contains("xxx.yyyz", pattern, "z"));
assertFalse(contains("xxx.yyyzz", pattern));
// 以?开始
pattern = ClassNameWildcardCompiler.compileClassName("?xxx.yyy");
assertTrue(contains("zxxx.yyy", pattern, "z"));
assertFalse(contains("zzxxx.yyy", pattern));
pattern = ClassNameWildcardCompiler.compileClassName("");
assertTrue(contains("", pattern));
assertTrue(contains("xxx.yyy", pattern));
}
@Test
public void classNameRelevant() {
assertEquals(0, ClassNameWildcardCompiler.getClassNameRelevancy(null));
assertEquals(0, ClassNameWildcardCompiler.getClassNameRelevancy(" "));
assertEquals(0, ClassNameWildcardCompiler.getClassNameRelevancy(""));
assertEquals(0, ClassNameWildcardCompiler.getClassNameRelevancy("*.**"));
assertEquals(1, ClassNameWildcardCompiler.getClassNameRelevancy("a?.**"));
assertEquals(3, ClassNameWildcardCompiler.getClassNameRelevancy("a?.**.bc"));
}
@Test
public void normalizePathName() {
assertEquals(null, PathNameWildcardCompiler.normalizePathName(null));
assertEquals("", PathNameWildcardCompiler.normalizePathName(" "));
assertEquals("/a/b/c/", PathNameWildcardCompiler.normalizePathName(" /a\\\\b//c// "));
assertEquals("a/b/c", PathNameWildcardCompiler.normalizePathName(" a\\\\b\\/c "));
assertEquals("/*/**/?/", PathNameWildcardCompiler.normalizePathName(" /*\\\\**//?// "));
assertEquals("*/**/?", PathNameWildcardCompiler.normalizePathName(" *\\\\**\\/? "));
}
@Test
public void normalizeClassName() {
assertEquals(null, ClassNameWildcardCompiler.normalizeClassName(null));
assertEquals("", ClassNameWildcardCompiler.normalizeClassName(" "));
assertEquals("a.b.c", ClassNameWildcardCompiler.normalizeClassName(" .a..b//c.. "));
assertEquals("a.b.c", ClassNameWildcardCompiler.normalizeClassName(" .a..b\\/c.. "));
assertEquals("*.**.?", ClassNameWildcardCompiler.normalizeClassName(" .*..**//?.. "));
assertEquals("*.**.?", ClassNameWildcardCompiler.normalizeClassName(" .*..**\\/?.. "));
}
@Test
public void classNameToPathName() {
assertEquals(null, ClassNameWildcardCompiler.classNameToPathName(null));
assertEquals("", ClassNameWildcardCompiler.classNameToPathName(" "));
assertEquals("a/b/c", ClassNameWildcardCompiler.classNameToPathName(" .a..b//c.. "));
assertEquals("a/b/c", ClassNameWildcardCompiler.classNameToPathName(" .a..b\\/c.. "));
assertEquals("*/**/?", ClassNameWildcardCompiler.classNameToPathName(" .*..**//?.. "));
assertEquals("*/**/?", ClassNameWildcardCompiler.classNameToPathName(" .*..**\\/?.. "));
}
@Test
public void stress() throws Exception {
final int concurrency = 10;
final int loops = 10000; // 100000;
final Pattern pattern = PathNameWildcardCompiler.compilePathName("/abc/def/**/ghi/*.jsp");
Runnable runnable = new Runnable() {
public void run() {
long start = System.currentTimeMillis();
for (int i = 0; i < loops; i++) {
assertTrue(contains("/abc/def/xyz/uvw/ghi/test.jsp", pattern, "xyz/uvw", "test"));
}
long duration = System.currentTimeMillis() - start;
System.out.println(Thread.currentThread().getName() + " takes " + getDuration(duration));
}
};
Thread[] threads = new Thread[concurrency];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(runnable, "Thread_" + i);
}
long start = System.currentTimeMillis();
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
thread.join();
}
long duration = System.currentTimeMillis() - start;
System.out.println("Total time: " + getDuration(duration));
}
private static String getDuration(long duration) {
long ms = duration % 1000;
long secs = duration / 1000 % 60;
long min = duration / 1000 / 60;
return MessageFormat.format("{0,choice,0#|.1#{0,number,integer}m}" + " {1,choice,0#|.1#{1,number,integer}s}"
+ " {2,number,integer}ms", min, secs, ms);
}
private boolean contains(String input, Pattern pattern, String... matches) {
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
assertEquals(matches.length, matcher.groupCount());
for (int i = 0; i < matches.length; i++) {
assertEquals(matches[i], matcher.group(i + 1));
}
return true;
} else {
assertTrue(isEmptyArray(matches));
return false;
}
}
}