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