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