2 * Copyright (c) 2013 Cisco Systems, Inc. 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.controller.yang.validator;
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.*;
15 import java.util.ArrayList;
16 import java.util.Date;
17 import java.util.HashSet;
18 import java.util.List;
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.controller.antlrv4.code.gen.YangParser.Augment_stmtContext;
25 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_add_stmtContext;
26 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_delete_stmtContext;
27 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviation_stmtContext;
28 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext;
29 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Include_stmtContext;
30 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext;
31 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext;
32 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext;
33 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext;
34 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext;
35 import org.opendaylight.controller.antlrv4.code.gen.YangParser.StringContext;
36 import org.opendaylight.controller.yang.parser.impl.YangParserListenerImpl;
37 import org.opendaylight.controller.yang.parser.util.YangValidationException;
39 import com.google.common.collect.Sets;
41 public class YangModelValidationTest {
43 private YangModelBasicValidationListener valid;
48 valid = new YangModelBasicValidationListener();
52 public void testPrefixes() {
53 Prefix_stmtContext pref = mockStatement(Prefix_stmtContext.class,
55 Module_stmtContext module = mockStatement(Module_stmtContext.class,
57 addChild(module, pref);
59 valid.enterPrefix_stmt(pref);
61 pref = mockStatement(Prefix_stmtContext.class, "unique1");
62 module = mockStatement(Module_stmtContext.class, "module1");
63 addChild(module, pref);
66 valid.enterPrefix_stmt(pref);
67 } catch (Exception e) {
71 fail("Validation Exception should have occured");
75 public void testNamespace() {
77 Namespace_stmtContext namespace = mockStatement(
78 Namespace_stmtContext.class, "http://test.parsing.uri.com");
79 Module_stmtContext module = mockStatement(Module_stmtContext.class,
81 addChild(module, namespace);
83 valid.enterNamespace_stmt(namespace);
85 namespace = mockStatement(Namespace_stmtContext.class, "invalid uri");
86 module = mockStatement(Module_stmtContext.class, "module1");
87 addChild(module, namespace);
90 valid.enterNamespace_stmt(namespace);
91 } catch (YangValidationException e) {
94 containsString("Namespace:invalid uri cannot be parsed as URI"));
98 fail("Validation Exception should have occured");
102 public void testImports() {
103 Import_stmtContext impor = mockImport("unique1", "p1");
104 Module_stmtContext mod = mockStatement(Module_stmtContext.class,
106 addChild(mod, impor);
108 valid.enterImport_stmt(impor);
110 impor = mockImport("unique1", "p2");
111 mod = mockStatement(Module_stmtContext.class, "module1");
112 addChild(mod, impor);
115 valid.enterImport_stmt(impor);
116 } catch (YangValidationException e) {
117 assertThat(e.getMessage(),
118 containsString("Import:unique1 not unique"));
122 fail("Validation Exception should have occured");
126 public void testIncludes() {
127 Include_stmtContext incl = mockInclude("unique1");
128 Module_stmtContext mod = mockStatement(Module_stmtContext.class,
131 valid.enterInclude_stmt(incl);
133 incl = mockInclude("unique1");
134 mod = mockStatement(Module_stmtContext.class, "module1");
138 valid.enterInclude_stmt(incl);
139 } catch (YangValidationException e) {
140 assertThat(e.getMessage(),
141 containsString("Include:unique1 not unique in (sub)module"));
145 fail("Validation Exception should have occured");
149 public void testIdentifierMatching() {
150 List<String> ids = new ArrayList<String>();
152 ids.add("_ok98-.87.-.8...88-asdAD");
161 for (String id : ids) {
163 Module_stmtContext module = mock(Module_stmtContext.class);
164 Token token = mock(Token.class);
165 when(module.getStart()).thenReturn(token);
166 BasicValidations.checkIdentifierInternal(
168 } catch (YangValidationException e) {
173 assertThat(thrown, is(3));
176 @Test(expected = YangValidationException.class)
177 public void testAugument() {
178 Augment_stmtContext augument = mockStatement(Augment_stmtContext.class,
179 "/a:*abc/a:augument1");
180 Module_stmtContext mod1 = mockStatement(Module_stmtContext.class,
182 addChild(mod1, augument);
184 Token token = mock(Token.class);
185 when(augument.getStart()).thenReturn(token);
188 valid.enterAugment_stmt(augument);
189 } catch (YangValidationException e) {
192 containsString("Schema node id:/a:*abc/a:augument1 not in required format, details:Prefixed id:a:*abc not in required format"));
198 public void testDeviate() {
199 Deviation_stmtContext ctx = mockStatement(Deviation_stmtContext.class,
201 Deviate_add_stmtContext add = mockStatement(
202 Deviate_add_stmtContext.class, "add");
203 Deviate_delete_stmtContext del = mockStatement(
204 Deviate_delete_stmtContext.class, "delete");
209 valid.enterDeviation_stmt(ctx);
211 HashSet<Class<? extends ParseTree>> types = Sets.newHashSet();
212 types.add(Deviate_add_stmtContext.class);
213 types.add(Deviate_delete_stmtContext.class);
215 int count = ValidationUtil.countPresentChildrenOfType(ctx, types);
216 assertThat(count, is(2));
219 @Test(expected = YangValidationException.class)
220 public void testStatus() throws Exception {
221 Status_argContext status = mockStatement(Status_argContext.class,
224 valid.enterStatus_arg(status);
225 } catch (YangValidationException e) {
228 containsString("illegal value for Status statement, only permitted:"));
233 private Import_stmtContext mockImport(String name, String prefixName) {
234 Import_stmtContext impor = mockStatement(Import_stmtContext.class, name);
236 Prefix_stmtContext prefix = mockStatement(Prefix_stmtContext.class,
238 Revision_date_stmtContext revDate = mockStatement(
239 Revision_date_stmtContext.class, getFormattedDate());
241 addChild(impor, prefix);
242 addChild(impor, revDate);
246 static String getFormattedDate() {
247 return YangParserListenerImpl.simpleDateFormat.format(new Date());
250 private Include_stmtContext mockInclude(String name) {
251 Include_stmtContext incl = mockStatement(Include_stmtContext.class,
254 Revision_date_stmtContext revDate = mockStatement(
255 Revision_date_stmtContext.class, getFormattedDate());
257 addChild(incl, revDate);
261 static void mockName(ParseTree stmt, String name) {
262 StringContext nameCtx = mock(StringContext.class);
263 ParseTree internalName = mock(ParseTree.class);
264 doReturn(1).when(stmt).getChildCount();
265 doReturn(name).when(internalName).getText();
266 doReturn(internalName).when(nameCtx).getChild(0);
267 doReturn(nameCtx).when(stmt).getChild(0);
270 static <T extends ParseTree> T mockStatement(Class<T> stmtType, String name) {
271 T stmt = stmtType.cast(mock(stmtType));
273 doReturn(0).when(stmt).getChildCount();
276 mockName(stmt, name);
280 static void addChild(ParseTree parent, ParseTree child) {
281 int childCount = parent.getChildCount() + 1;
282 doReturn(childCount).when(parent).getChildCount();
283 doReturn(child).when(parent).getChild(childCount - 1);
284 doReturn(parent).when(child).getParent();