Drop unneeded generic type specifiers
[yangtools.git] / yang / yang-parser-impl / src / test / java / org / opendaylight / yangtools / yang / parser / impl / YangModelValidationTest.java
1 /*
2  * Copyright (c) 2013 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.impl;
9
10 import static org.hamcrest.CoreMatchers.containsString;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertThat;
13 import static org.junit.Assert.fail;
14 import static org.mockito.Mockito.doReturn;
15 import static org.mockito.Mockito.mock;
16 import static org.mockito.Mockito.when;
17 import com.google.common.collect.Sets;
18 import java.text.SimpleDateFormat;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.Date;
22 import java.util.HashSet;
23 import java.util.List;
24 import org.antlr.v4.runtime.Token;
25 import org.antlr.v4.runtime.tree.ParseTree;
26 import org.antlr.v4.runtime.tree.TerminalNode;
27 import org.junit.Before;
28 import org.junit.Test;
29 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Augment_stmtContext;
30 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Deviate_add_stmtContext;
31 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Deviate_delete_stmtContext;
32 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Deviation_stmtContext;
33 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Import_stmtContext;
34 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Include_stmtContext;
35 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Module_stmtContext;
36 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Namespace_stmtContext;
37 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Prefix_stmtContext;
38 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Revision_date_stmtContext;
39 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Status_argContext;
40 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.StringContext;
41 import org.opendaylight.yangtools.yang.parser.util.YangValidationException;
42
43 public class YangModelValidationTest {
44
45     private YangModelBasicValidationListener valid;
46
47     @Before
48     public void setUp() {
49
50         valid = new YangModelBasicValidationListener();
51     }
52
53     @Test
54     public void testPrefixes() {
55         Prefix_stmtContext pref = mockStatement(Prefix_stmtContext.class, "unique1");
56         Module_stmtContext module = mockStatement(Module_stmtContext.class, "module1");
57         addChild(module, pref);
58
59         valid.enterPrefix_stmt(pref);
60
61         pref = mockStatement(Prefix_stmtContext.class, "unique1");
62         module = mockStatement(Module_stmtContext.class, "module1");
63         addChild(module, pref);
64
65         try {
66             valid.enterPrefix_stmt(pref);
67         } catch (Exception e) {
68             return;
69         }
70
71         fail("Validation Exception should have occured");
72     }
73
74     @Test
75     public void testNamespace() {
76
77         Namespace_stmtContext namespace = mockStatement(Namespace_stmtContext.class, "http://test.parsing.uri.com");
78         Module_stmtContext module = mockStatement(Module_stmtContext.class, "module1");
79         addChild(module, namespace);
80
81         valid.enterNamespace_stmt(namespace);
82
83         namespace = mockStatement(Namespace_stmtContext.class, "invalid uri");
84         module = mockStatement(Module_stmtContext.class, "module1");
85         addChild(module, namespace);
86
87         try {
88             valid.enterNamespace_stmt(namespace);
89         } catch (YangValidationException e) {
90             assertThat(e.getMessage(), containsString("Namespace:invalid uri cannot be parsed as URI"));
91             return;
92         }
93
94         fail("Validation Exception should have occured");
95     }
96
97     @Test
98     public void testImports() {
99         Import_stmtContext impor = mockImport("unique1", "p1");
100         Module_stmtContext mod = mockStatement(Module_stmtContext.class, "module1");
101         addChild(mod, impor);
102
103         valid.enterImport_stmt(impor);
104
105         impor = mockImport("unique1", "p2");
106         mod = mockStatement(Module_stmtContext.class, "module1");
107         addChild(mod, impor);
108
109         try {
110             valid.enterImport_stmt(impor);
111         } catch (YangValidationException e) {
112             assertThat(e.getMessage(), containsString("Import:unique1 not unique"));
113             return;
114         }
115
116         fail("Validation Exception should have occured");
117     }
118
119     @Test
120     public void testIncludes() {
121         Include_stmtContext incl = mockInclude("unique1");
122         Module_stmtContext mod = mockStatement(Module_stmtContext.class, "module1");
123         addChild(mod, incl);
124         valid.enterInclude_stmt(incl);
125
126         incl = mockInclude("unique1");
127         mod = mockStatement(Module_stmtContext.class, "module1");
128         addChild(mod, incl);
129
130         try {
131             valid.enterInclude_stmt(incl);
132         } catch (YangValidationException e) {
133             assertThat(e.getMessage(), containsString("Include:unique1 not unique in (sub)module"));
134             return;
135         }
136
137         fail("Validation Exception should have occured");
138     }
139
140     @Test
141     public void testIdentifierMatching() {
142         List<String> ids = new ArrayList<>();
143         // valid
144         ids.add("_ok98-.87.-.8...88-asdAD");
145         ids.add("AA.bcd");
146         ids.add("a");
147         // invalid
148         ids.add("9aa");
149         ids.add("-");
150         ids.add(".");
151
152         int thrown = 0;
153         for (String id : ids) {
154             try {
155                 Module_stmtContext module = mock(Module_stmtContext.class);
156                 Token token = mock(Token.class);
157                 when(module.getStart()).thenReturn(token);
158                 BasicValidations.checkIdentifierInternal(module, id);
159             } catch (YangValidationException e) {
160                 thrown++;
161             }
162         }
163
164         assertEquals(3, thrown);
165     }
166
167     @Test(expected = YangValidationException.class)
168     public void testAugument() {
169         Augment_stmtContext augument = mockStatement(Augment_stmtContext.class, "/a:*abc/a:augument1");
170         Module_stmtContext mod1 = mockStatement(Module_stmtContext.class, "mod1");
171         addChild(mod1, augument);
172
173         Token token = mock(Token.class);
174         when(augument.getStart()).thenReturn(token);
175
176         try {
177             valid.enterAugment_stmt(augument);
178         } catch (YangValidationException e) {
179             assertThat(
180                     e.getMessage(),
181                     containsString("Schema node id:/a:*abc/a:augument1 not in required format, details:Prefixed id:a:*abc not in required format"));
182             throw e;
183         }
184     }
185
186     @Test
187     public void testDeviate() {
188         Deviation_stmtContext ctx = mockStatement(Deviation_stmtContext.class, "deviations");
189         Deviate_add_stmtContext add = mockStatement(Deviate_add_stmtContext.class, "add");
190         Deviate_delete_stmtContext del = mockStatement(Deviate_delete_stmtContext.class, "delete");
191
192         addChild(ctx, add);
193         addChild(ctx, del);
194
195         valid.enterDeviation_stmt(ctx);
196
197         HashSet<Class<? extends ParseTree>> types = Sets.newHashSet();
198         types.add(Deviate_add_stmtContext.class);
199         types.add(Deviate_delete_stmtContext.class);
200
201         int count = ValidationUtil.countPresentChildrenOfType(ctx, types);
202         assertEquals(2, count);
203     }
204
205     @Test(expected = YangValidationException.class)
206     public void testStatus() throws Exception {
207         Status_argContext status = mockStatement(Status_argContext.class, "unknown");
208         try {
209             valid.enterStatus_arg(status);
210         } catch (YangValidationException e) {
211             assertThat(e.getMessage(), containsString("illegal value for Status statement, only permitted:"));
212             throw e;
213         }
214     }
215
216     private static Import_stmtContext mockImport(final String name, final String prefixName) {
217         Import_stmtContext impor = mockStatement(Import_stmtContext.class, name);
218
219         Prefix_stmtContext prefix = mockStatement(Prefix_stmtContext.class, prefixName);
220         Revision_date_stmtContext revDate = mockStatement(Revision_date_stmtContext.class, getFormattedDate());
221
222         addChild(impor, prefix);
223         addChild(impor, revDate);
224         return impor;
225     }
226
227     static String getFormattedDate() {
228         return new SimpleDateFormat("yyyy-MM-dd").format(new Date());
229     }
230
231     private static Include_stmtContext mockInclude(final String name) {
232         Include_stmtContext incl = mockStatement(Include_stmtContext.class, name);
233
234         Revision_date_stmtContext revDate = mockStatement(Revision_date_stmtContext.class, getFormattedDate());
235
236         addChild(incl, revDate);
237         return incl;
238     }
239
240     static void mockName(final ParseTree stmt, final String name) {
241         doReturn(1).when(stmt).getChildCount();
242
243         TerminalNode terminalNode = mock(TerminalNode.class);
244         doReturn(name).when(terminalNode).getText();
245
246         StringContext nameCtx = mock(StringContext.class);
247         doReturn(nameCtx).when(stmt).getChild(0);
248         doReturn(terminalNode).when(nameCtx).getChild(0);
249         doReturn(name).when(terminalNode).getText();
250
251         doReturn(Collections.singletonList(terminalNode)).when(nameCtx).STRING();
252     }
253
254     static <T extends ParseTree> T mockStatement(final Class<T> stmtType, final String name) {
255         T stmt = stmtType.cast(mock(stmtType));
256
257         doReturn(0).when(stmt).getChildCount();
258
259         if (name != null) {
260             mockName(stmt, name);
261         }
262         return stmt;
263     }
264
265     static void addChild(final ParseTree parent, final ParseTree child) {
266         int childCount = parent.getChildCount() + 1;
267         doReturn(childCount).when(parent).getChildCount();
268         doReturn(child).when(parent).getChild(childCount - 1);
269         doReturn(parent).when(child).getParent();
270     }
271
272 }