blob: 80f049d1e4579396265607d05e766c80b14b5bdc [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.sling.scripting.sightly.impl.utils;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.regex.Pattern;
import org.junit.Test;
import static org.junit.Assert.fail;
public class PatternsTest {
private static final int REGEX_MATCH_TIMEOUT = 3;
@Test
public void testJavaPackagePattern() {
Object[] inputs = new Object[]{
"package org.apache.sling.scripting.sightly.impl.utils; ", true,
"package org.apache.sling.scripting.sightly.impl_utils; ", true,
"package org.apache.sling.scripting.sightly.impl_utils;", true,
"package org.apache.sling.scripting.sightly.impl.utils;", true,
"package $org.apache.sling.scripting.sightly.impl.utils;", true,
"package _org.apache.sling.scripting.sightly.impl.utils;", true,
"package org.apa_che.sling.scripting.sightly.impl.utils;", true,
"package org.ap$che.sling.scripting.sightly.impl.utils;", true,
"package org.ap4che.$sling._scripting.sightly.impl.utils;", true,
"package 1org.apache.sling.scripting.sightly.impl.utils;", false,
"package org.1apache.sling.scripting.sightly.impl.utils;", false,
"package\torg.apache.sling.scripting.sightly.impl.utils;\t", true,
"package org.apache.sling.scripting.sightly.impl.utils ; ", true,
};
testPattern(Patterns.JAVA_PACKAGE_DECLARATION, inputs);
}
@Test
public void testJavaClassNamePattern() {
Object[] inputs = new Object[]{
"org.apache.sling.scripting.sightly.impl.utils.PatternsTest", true,
"$org.apache.sling.scripting.sightly.impl.utils.PatternsTest", true,
"_org.apache.sling.scripting.sightly.impl.utils.PatternsTest", true,
"PatternsTest", true,
"PatternsTest2", true,
"PatternsTest ", false,
"1PatternsTest", false,
"$", true,
"_", true,
"$_", true,
"$_1", true,
"package_info", true,
};
testPattern(Patterns.JAVA_CLASS_NAME, inputs);
}
// @Test
// public void testSLING_7523Pattern() {
// // pattern from org.apache.sling.scripting.sightly.impl.engine.SightlyJavaCompilerService before SLING-7523
// Pattern PACKAGE_DECL_PATTERN = Pattern.compile("(\\s*)package\\s+([a-zA-Z_$][a-zA-Z\\d_$]*\\.?)+;");
// Object[] inputs = new Object[]{
// "package org.apache.sling.scripting.sightly.impl.utils; ", true,
// "package org.apache.sling.scripting.sightly.impl_utils; ", true,
// "package org.apache.sling.scripting.sightly.impl_utils;", true,
// "package org.apache.sling.scripting.sightly.impl.utils;", true,
// "package $org.apache.sling.scripting.sightly.impl.utils;", true,
// "package _org.apache.sling.scripting.sightly.impl.utils;", true,
// "package org.apa_che.sling.scripting.sightly.impl.utils;", true,
// "package org.ap$che.sling.scripting.sightly.impl.utils;", true,
// "package org.ap4che.$sling._scripting.sightly.impl.utils;", true,
// "package 1org.apache.sling.scripting.sightly.impl.utils;", false,
// "package org.1apache.sling.scripting.sightly.impl.utils;", false,
// "package\torg.apache.sling.scripting.sightly.impl.utils;\t", true,
// "package org.apache.sling.scripting.sightly.impl.utils ; ", true,
// };
// testPattern(PACKAGE_DECL_PATTERN, inputs);
// }
private void testPattern(Pattern pattern, Object[] inputs) {
StringBuilder errors = new StringBuilder();
ExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadExecutor();
for (int i = 0; i < inputs.length - 1; i += 2) {
String input = (String) inputs[i];
boolean expectedMatch = (Boolean) inputs[i + 1];
Future<Boolean> future = EXECUTOR_SERVICE.submit(new PatternCallable(pattern, input));
try {
if (expectedMatch != future.get(REGEX_MATCH_TIMEOUT, TimeUnit.SECONDS)) {
errors.append(
String.format(
"Pattern '%s' %s '%s'.", pattern, expectedMatch ? "was expected to match" : "was not expected to match", input
)
).append("\n");
}
} catch (TimeoutException e) {
errors.append(
String.format(
"Pattern '%s' is susceptible to catastrophic backtracking for input '%s'.",
Patterns.JAVA_PACKAGE_DECLARATION.pattern(),
input
)
).append("\n");
future.cancel(true);
EXECUTOR_SERVICE.shutdownNow();
EXECUTOR_SERVICE = Executors.newSingleThreadExecutor();
} catch (Exception e) {
errors.append(
String.format(
"Unable to test pattern '%s' with input '%s': %s.",
Patterns.JAVA_PACKAGE_DECLARATION.pattern(),
input,
e.getMessage()
)
).append("\n");
}
}
if (errors.length() > 0) {
fail("\n" + errors.toString());
}
}
class PatternCallable implements Callable<Boolean> {
private Pattern pattern;
private String toMatch;
PatternCallable(Pattern pattern, String toMatch) {
this.pattern = pattern;
this.toMatch = toMatch;
}
@Override
public Boolean call() {
return pattern.matcher(toMatch).matches();
}
}
}