62654c814e604d7e6d68d621b70e825772150cc6
[yangtools.git] / yang / yang-parser-impl / src / test / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / Bug5410Test.java
1 /*
2  * Copyright (c) 2017 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertTrue;
14
15 import com.google.common.collect.ImmutableList;
16 import java.io.ByteArrayOutputStream;
17 import java.io.PrintStream;
18 import java.io.UnsupportedEncodingException;
19 import java.util.List;
20 import org.junit.Test;
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
25 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
26 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
27 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
28 import org.opendaylight.yangtools.yang.model.util.RegexUtils;
29 import org.opendaylight.yangtools.yang.stmt.StmtTestUtils;
30
31 public class Bug5410Test {
32     private static final String FOO_NS = "foo";
33     private static final String FOO_REV = "1970-01-01";
34
35     @Test
36     public void testJavaRegexFromXSD() {
37         testPattern("^[^:]+$", "^\\^[^:]+\\$$", ImmutableList.of("^a$", "^abc$"),
38                 ImmutableList.of("abc$", "^abc", "^a:bc$"));
39         testPattern("^[$^]$", "^\\^[$^]\\$$", ImmutableList.of("^^$", "^$$"), ImmutableList.of("^^", "^$", "$^", "$$"));
40         testPattern("[$-%]+", "^[$-%]+$", ImmutableList.of("$", "%", "%$"), ImmutableList.of("$-", "$-%", "-", "^"));
41         testPattern("[$-&]+", "^[$-&]+$", ImmutableList.of("$", "%&", "%$", "$%&"), ImmutableList.of("#", "$-&", "'"));
42
43         testPattern("[a-z&&[^m-p]]+", "^[a-z&&[^m-p]]+$", ImmutableList.of("a", "z", "az"),
44                 ImmutableList.of("m", "anz", "o"));
45         testPattern("^[\\[-b&&[^^-a]]+$", "^\\^[\\[-b&&[^^-a]]+\\$$", ImmutableList.of("^[$", "^\\$", "^]$", "^b$"),
46                 ImmutableList.of("^a$", "^^$", "^_$"));
47
48         testPattern("[^^-~&&[^$-^]]", "^[^^-~&&[^$-^]]$", ImmutableList.of("!", "\"", "#"),
49                 ImmutableList.of("a", "A", "z", "Z", "$", "%", "^", "}"));
50         testPattern("\\\\\\[^[^^-~&&[^$-^]]", "^\\\\\\[\\^[^^-~&&[^$-^]]$",
51                 ImmutableList.of("\\[^ ", "\\[^!", "\\[^\"", "\\[^#"),
52                 ImmutableList.of("\\[^a", "\\[^A", "\\[^z", "\\[^Z", "\\[^$", "\\[^%", "\\[^^", "\\[^}"));
53         testPattern("^\\[^\\\\[^^-b&&[^\\[-\\]]]\\]^", "^\\^\\[\\^\\\\[^^-b&&[^\\[-\\]]]\\]\\^$",
54                 ImmutableList.of("^[^\\c]^", "^[^\\Z]^"),
55                 ImmutableList.of("^[^\\[]^", "^[^\\\\]^", "^[^\\]]^", "^[^\\^]^", "^[^\\_]^", "^[^\\b]^"));
56         testPattern("[\\^]$", "^[\\^]\\$$", ImmutableList.of("^$"),
57                 ImmutableList.of("^", "$", "$^", "\\", "\\^", "\\^\\", "\\^\\$"));
58     }
59
60     @Test
61     public void testInvalidXSDRegexes() throws UnsupportedEncodingException {
62         testInvalidPattern("$^a^[$^\\]", "Unclosed character class");
63         testInvalidPattern("$(\\)", "Unclosed group");
64     }
65
66     @Test
67     public void testJavaPattern() {
68         testPattern("^[$^]+$", ImmutableList.of("$^", "^", "$"), ImmutableList.of("\\", "a"));
69         testPattern("^[^$-^]$", ImmutableList.of("a", "_", "#"), ImmutableList.of("%", "^", "$", "]", "\\"));
70     }
71
72     @Test
73     public void testYangPattern() throws Exception {
74         final SchemaContext context = StmtTestUtils.parseYangSources("/bugs/bug5410");
75         assertNotNull(context);
76
77         final PatternConstraint pattern = getPatternConstraintOf(context, "leaf-with-pattern");
78
79         final String rawRegex = pattern.getRawRegularExpression();
80         final String expectedYangRegex = "$0$.*|$1$[a-zA-Z0-9./]{1,8}$[a-zA-Z0-9./]{22}|$5$(rounds=\\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{43}|$6$(rounds=\\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{86}";
81         assertEquals(expectedYangRegex, rawRegex);
82
83         final String javaRegexFromYang = pattern.getRegularExpression();
84         final String expectedJavaRegex = "^\\$0\\$.*|\\$1\\$[a-zA-Z0-9./]{1,8}\\$[a-zA-Z0-9./]{22}|\\$5\\$(rounds=\\d+\\$)?[a-zA-Z0-9./]{1,16}\\$[a-zA-Z0-9./]{43}|\\$6\\$(rounds=\\d+\\$)?[a-zA-Z0-9./]{1,16}\\$[a-zA-Z0-9./]{86}$";
85         assertEquals(expectedJavaRegex, javaRegexFromYang);
86
87         final String value = "$6$AnrKGc0V$B/0/A.pWg4HrrA6YiEJOtFGibQ9Fmm5.4rI/00gEz3QeB7joSxBU3YtbHDm6NSkS1dKTQy3BWhwKKDS8nB5S//";
88         testPattern(javaRegexFromYang, ImmutableList.of(value), ImmutableList.of());
89     }
90
91     @Test
92     public void testCaret() {
93         testPattern("^", "\\^");
94     }
95
96     @Test
97     public void testTextCaret() {
98         testPattern("abc^", "abc\\^");
99     }
100
101     @Test
102     public void testTextDollar() {
103         testPattern("abc$", "abc\\$");
104     }
105
106     @Test
107     public void testCaretCaret() {
108         testPattern("^^", "\\^\\^");
109     }
110
111     @Test
112     public void testCaretDollar() {
113         testPattern("^$", "\\^\\$");
114     }
115
116     @Test
117     public void testDot() {
118         testPattern(".", ".");
119     }
120
121     @Test
122     public void testNotColon() {
123         testPattern("[^:]+", "[^:]+");
124     }
125
126     @Test
127     public void testDollar() {
128         testPattern("$", "\\$");
129     }
130
131     @Test
132     public void testDollarOneDollar() {
133         testPattern("$1$", "\\$1\\$");
134     }
135
136     @Test
137     public void testDollarPercentRange() {
138         testPattern("[$-%]+", "[$-%]+");
139     }
140
141     @Test
142     public void testDollarRange() {
143         testPattern("[$$]+", "[$$]+");
144     }
145
146     @Test
147     public void testDollarCaretRange() {
148         testPattern("[$^]+", "[$^]+");
149     }
150
151     @Test
152     public void testSimple() {
153         testPattern("abc", "abc");
154     }
155
156     @Test
157     public void testDotPlus() {
158         testPattern(".+", ".+");
159     }
160
161     @Test
162     public void testDotStar() {
163         testPattern(".*", ".*");
164     }
165
166     @Test
167     public void testSimpleOptional() {
168         testPattern("a?", "a?");
169     }
170
171     @Test
172     public void testRangeOptional() {
173         testPattern("[a-z]?", "[a-z]?");
174     }
175
176     private static void testPattern(final String xsdRegex, final String expectedJavaRegex,
177             final List<String> positiveMatches, final List<String> negativeMatches) {
178         final String javaRegexFromXSD = javaRegexFromXSD(xsdRegex);
179         assertEquals(expectedJavaRegex, javaRegexFromXSD);
180
181         for (final String value : positiveMatches) {
182             assertTrue("Value '" + value + "' does not match java regex '" + javaRegexFromXSD + "'",
183                     testMatch(javaRegexFromXSD, value));
184         }
185         for (final String value : negativeMatches) {
186             assertFalse("Value '" + value + "' matches java regex '" + javaRegexFromXSD + "'",
187                     testMatch(javaRegexFromXSD, value));
188         }
189     }
190
191     private static void testPattern(final String javaRegex, final List<String> positiveMatches,
192             final List<String> negativeMatches) {
193         for (final String value : positiveMatches) {
194             assertTrue("Value '" + value + "' does not match java regex '" + javaRegex + "'",
195                     testMatch(javaRegex, value));
196         }
197         for (final String value : negativeMatches) {
198             assertFalse("Value '" + value + "' matches java regex '" + javaRegex + "'", testMatch(javaRegex, value));
199         }
200     }
201
202     private static String javaRegexFromXSD(final String xsdRegex) {
203         return RegexUtils.getJavaRegexFromXSD(xsdRegex);
204     }
205
206     private static boolean testMatch(final String javaRegex, final String value) {
207         return value.matches(javaRegex);
208     }
209
210     private static void testPattern(final String xsdRegex, final String unanchoredJavaRegex) {
211         testPattern(xsdRegex, '^' + unanchoredJavaRegex + '$', ImmutableList.of(), ImmutableList.of());
212     }
213
214     private static PatternConstraint getPatternConstraintOf(final SchemaContext context, final String leafName) {
215         final DataSchemaNode dataChildByName = context.getDataChildByName(foo(leafName));
216         assertTrue(dataChildByName instanceof LeafSchemaNode);
217         final LeafSchemaNode leaf = (LeafSchemaNode) dataChildByName;
218         final TypeDefinition<? extends TypeDefinition<?>> type = leaf.getType();
219         assertTrue(type instanceof StringTypeDefinition);
220         final StringTypeDefinition strType = (StringTypeDefinition) type;
221         return strType.getPatternConstraints().iterator().next();
222     }
223
224     private static QName foo(final String localName) {
225         return QName.create(FOO_NS, FOO_REV, localName);
226     }
227
228     private static void testInvalidPattern(final String xsdRegex, final String expectedMessage) throws UnsupportedEncodingException {
229         final PrintStream stdout = System.out;
230         final ByteArrayOutputStream output = new ByteArrayOutputStream();
231         System.setOut(new PrintStream(output, true, "UTF-8"));
232
233         javaRegexFromXSD(xsdRegex);
234
235         final String testLog = output.toString();
236         assertTrue(testLog.contains(expectedMessage));
237         System.setOut(stdout);
238     }
239 }