2 * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.pattern;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertTrue;
14 import com.google.common.collect.ImmutableList;
15 import java.io.ByteArrayOutputStream;
16 import java.io.PrintStream;
17 import java.io.UnsupportedEncodingException;
18 import java.nio.charset.StandardCharsets;
19 import java.util.List;
20 import org.junit.Test;
22 public class Bug5410Test {
24 public void testCaret() {
25 testPattern("^", "\\^");
29 public void testTextCaret() {
30 testPattern("abc^", "abc\\^");
34 public void testTextDollar() {
35 testPattern("abc$", "abc\\$");
39 public void testCaretCaret() {
40 testPattern("^^", "\\^\\^");
44 public void testCaretDollar() {
45 testPattern("^$", "\\^\\$");
49 public void testDot() {
50 testPattern(".", ".");
54 public void testNotColon() {
55 testPattern("[^:]+", "[^:]+");
59 public void testDollar() {
60 testPattern("$", "\\$");
64 public void testDollarOneDollar() {
65 testPattern("$1$", "\\$1\\$");
69 public void testDollarPercentRange() {
70 testPattern("[$-%]+", "[$-%]+");
74 public void testDollarRange() {
75 testPattern("[$$]+", "[$$]+");
79 public void testDollarCaretRange() {
80 testPattern("[$^]+", "[$^]+");
84 public void testSimple() {
85 testPattern("abc", "abc");
89 public void testDotPlus() {
90 testPattern(".+", ".+");
94 public void testDotStar() {
95 testPattern(".*", ".*");
99 public void testSimpleOptional() {
100 testPattern("a?", "a?");
104 public void testRangeOptional() {
105 testPattern("[a-z]?", "[a-z]?");
109 public void testInvalidXSDRegexes() throws UnsupportedEncodingException {
110 testInvalidPattern("$^a^[$^\\]", "Unclosed character class");
111 testInvalidPattern("$(\\)", "Unclosed group");
115 public void testJavaPattern() {
116 testPattern("^[$^]+$", ImmutableList.of("$^", "^", "$"), ImmutableList.of("\\", "a"));
117 testPattern("^[^$-^]$", ImmutableList.of("a", "_", "#"), ImmutableList.of("%", "^", "$", "]", "\\"));
121 public void testJavaRegexFromXSD() {
122 testPattern("^[^:]+$", "^(?:\\^[^:]+\\$)$", ImmutableList.of("^a$", "^abc$"),
123 ImmutableList.of("abc$", "^abc", "^a:bc$"));
124 testPattern("^[$^]$", "^(?:\\^[$^]\\$)$", ImmutableList.of("^^$", "^$$"),
125 ImmutableList.of("^^", "^$", "$^", "$$"));
126 testPattern("[$-%]+", "^(?:[$-%]+)$", ImmutableList.of("$", "%", "%$"),
127 ImmutableList.of("$-", "$-%", "-", "^"));
128 testPattern("[$-&]+", "^(?:[$-&]+)$", ImmutableList.of("$", "%&", "%$", "$%&"),
129 ImmutableList.of("#", "$-&", "'"));
131 testPattern("[a-z&&[^m-p]]+", "^(?:[a-z&&[^m-p]]+)$", ImmutableList.of("a", "z", "az"),
132 ImmutableList.of("m", "anz", "o"));
133 testPattern("^[\\[-b&&[^^-a]]+$", "^(?:\\^[\\[-b&&[^^-a]]+\\$)$", ImmutableList.of("^[$", "^\\$", "^]$", "^b$"),
134 ImmutableList.of("^a$", "^^$", "^_$"));
136 // FIXME: YANGTOOLS-887: these patterns are not translated correctly, "&&" is a different construct in XSD
137 // testPattern("[^^-~&&[^$-^]]", "^(?:[^^-~&&[^$-^]])$", ImmutableList.of("!", "\"", "#"),
138 // ImmutableList.of("a", "A", "z", "Z", "$", "%", "^", "}"));
139 // testPattern("\\\\\\[^[^^-~&&[^$-^]]", "^(?:\\\\\\[\\^[^^-~&&[^$-^]])$",
140 // ImmutableList.of("\\[^ ", "\\[^!", "\\[^\"", "\\[^#"),
141 // ImmutableList.of("\\[^a", "\\[^A", "\\[^z", "\\[^Z", "\\[^$", "\\[^%", "\\[^^", "\\[^}"));
142 // testPattern("^\\[^\\\\[^^-b&&[^\\[-\\]]]\\]^", "^(?:\\^\\[\\^\\\\[^^-b&&[^\\[-\\]]]\\]\\^)$",
143 // ImmutableList.of("^[^\\c]^", "^[^\\Z]^"),
144 // ImmutableList.of("^[^\\[]^", "^[^\\\\]^", "^[^\\]]^", "^[^\\^]^", "^[^\\_]^", "^[^\\b]^"));
145 // testPattern("[\\^]$", "^(?:[\\^]\\$)$", ImmutableList.of("^$"),
146 // ImmutableList.of("^", "$", "$^", "\\", "\\^", "\\^\\", "\\^\\$"));
149 @SuppressWarnings("checkstyle:regexpSinglelineJava")
150 private static void testInvalidPattern(final String xsdRegex, final String expectedMessage)
151 throws UnsupportedEncodingException {
152 final PrintStream stdout = System.out;
153 final ByteArrayOutputStream output = new ByteArrayOutputStream();
154 System.setOut(new PrintStream(output, true, StandardCharsets.UTF_8));
156 RegexUtils.getJavaRegexFromXSD(xsdRegex);
158 final String testLog = output.toString();
159 assertTrue(testLog.contains(expectedMessage));
160 System.setOut(stdout);
163 private static boolean testMatch(final String javaRegex, final String value) {
164 return value.matches(javaRegex);
167 private static void testPattern(final String xsdRegex, final String unanchoredJavaRegex) {
168 testPattern(xsdRegex, "^(?:" + unanchoredJavaRegex + ")$", ImmutableList.of(), ImmutableList.of());
171 private static void testPattern(final String javaRegex, final List<String> positiveMatches,
172 final List<String> negativeMatches) {
173 for (final String value : positiveMatches) {
174 assertTrue("Value '" + value + "' does not match java regex '" + javaRegex + "'",
175 testMatch(javaRegex, value));
177 for (final String value : negativeMatches) {
178 assertFalse("Value '" + value + "' matches java regex '" + javaRegex + "'", testMatch(javaRegex, value));
182 private static void testPattern(final String xsdRegex, final String expectedJavaRegex,
183 final List<String> positiveMatches, final List<String> negativeMatches) {
184 final String javaRegexFromXSD = RegexUtils.getJavaRegexFromXSD(xsdRegex);
185 assertEquals(expectedJavaRegex, javaRegexFromXSD);
187 for (final String value : positiveMatches) {
188 assertTrue("Value '" + value + "' does not match java regex '" + javaRegexFromXSD + "'",
189 testMatch(javaRegexFromXSD, value));
191 for (final String value : negativeMatches) {
192 assertFalse("Value '" + value + "' matches java regex '" + javaRegexFromXSD + "'",
193 testMatch(javaRegexFromXSD, value));