BUG-1210: refactored imports handling in parser.
[yangtools.git] / yang / yang-parser-impl / src / test / java / org / opendaylight / yangtools / yang / parser / util / ModuleDependencySortTest.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.util;
9
10 import static org.hamcrest.core.AnyOf.anyOf;
11 import static org.hamcrest.core.Is.is;
12 import static org.junit.Assert.assertThat;
13 import static org.junit.matchers.JUnitMatchers.containsString;
14 import static org.mockito.Mockito.doReturn;
15 import static org.mockito.Mockito.mock;
16
17 import com.google.common.collect.Sets;
18 import java.text.DateFormat;
19 import java.text.SimpleDateFormat;
20 import java.util.Arrays;
21 import java.util.Collections;
22 import java.util.Date;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Map.Entry;
27 import java.util.Set;
28 import org.hamcrest.Matcher;
29 import org.junit.Test;
30 import org.opendaylight.yangtools.yang.model.api.Module;
31 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
32 import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder;
33 import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort.ModuleNodeImpl;
34 import org.opendaylight.yangtools.yang.parser.util.TopologicalSort.Edge;
35
36 public class ModuleDependencySortTest {
37     private final DateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
38     private final ModuleBuilder a = mockModuleBuilder("a", null);
39     private final ModuleBuilder b = mockModuleBuilder("b", null);
40     private final ModuleBuilder c = mockModuleBuilder("c", null);
41     private final ModuleBuilder d = mockModuleBuilder("d", null);
42
43     @Test
44     public void testValid() throws Exception {
45
46         mockDependency(a, b);
47         mockDependency(b, c);
48         mockDependency(b, d);
49
50         ModuleBuilder[] builders = new ModuleBuilder[] { d, b, c, a };
51
52         List<ModuleBuilder> l = ModuleDependencySort.sort(builders);
53
54         assertDependencyGraph(ModuleDependencySort.createModuleGraph(ModuleOrModuleBuilder.fromAll(
55                 Collections.<Module>emptySet(), Arrays.asList(builders))));
56
57         @SuppressWarnings("unchecked")
58         Matcher<String> cOrD = anyOf(is(c.getName()), is(d.getName()));
59
60         assertThat(l.get(0).getName(), cOrD);
61         assertThat(l.get(1).getName(), cOrD);
62         assertThat(l.get(2).getName(), is(b.getName()));
63         assertThat(l.get(3).getName(), is(a.getName()));
64     }
65
66     @Test
67     public void testValidModule() throws Exception {
68
69         Date rev = new Date();
70         Module a = mockModule("a", rev);
71         Module b = mockModule("b", rev);
72         Module c = mockModule("c", rev);
73
74         mockDependency(a, b);
75         mockDependency(b, c);
76         mockDependency(a, c);
77
78         Module[] builders = new Module[] { a, b, c };
79
80         List<Module> l = ModuleDependencySort.sort(builders);
81
82         assertThat(l.get(0).getName(), is(c.getName()));
83         assertThat(l.get(1).getName(), is(b.getName()));
84         assertThat(l.get(2).getName(), is(a.getName()));
85     }
86
87     @Test(expected = YangValidationException.class)
88     public void testModuleTwice() throws Exception {
89         ModuleBuilder a2 = mockModuleBuilder("a", null);
90
91         ModuleBuilder[] builders = new ModuleBuilder[] { a, a2 };
92         try {
93             ModuleDependencySort.sort(builders);
94         } catch (YangValidationException e) {
95             assertThat(e.getMessage(), containsString("Module:a with revision:default declared twice"));
96             throw e;
97         }
98     }
99
100     @Test(expected = YangValidationException.class)
101     public void testImportNotExistingModule() throws Exception {
102         mockDependency(a, b);
103
104         ModuleBuilder[] builders = new ModuleBuilder[] { a };
105         try {
106             ModuleDependencySort.sort(builders);
107         } catch (YangValidationException e) {
108             assertThat(e.getMessage(), containsString("Not existing module imported:b:default by:a:default"));
109             throw e;
110         }
111     }
112
113     @Test
114     public void testImportTwice() throws Exception {
115         mockDependency(a, b);
116         mockDependency(c, b);
117
118         ModuleBuilder[] builders = new ModuleBuilder[] { a, b, c };
119         ModuleDependencySort.sort(builders);
120     }
121
122     @Test
123     public void testModuleTwiceWithDifferentRevs() throws Exception {
124         ModuleBuilder a2 = mockModuleBuilder("a", new Date());
125
126         ModuleBuilder[] builders = new ModuleBuilder[] { a, a2 };
127         ModuleDependencySort.sort(builders);
128     }
129
130     @Test(expected = YangValidationException.class)
131     public void testModuleTwice2() throws Exception {
132         Date rev = new Date();
133         ModuleBuilder a2 = mockModuleBuilder("a", rev);
134         ModuleBuilder a3 = mockModuleBuilder("a", rev);
135
136         ModuleBuilder[] builders = new ModuleBuilder[] { a, a2, a3 };
137         try {
138             ModuleDependencySort.sort(builders);
139         } catch (YangValidationException e) {
140             assertThat(e.getMessage(), containsString("Module:a with revision:" + SIMPLE_DATE_FORMAT.format(rev)
141                     + " declared twice"));
142             throw e;
143         }
144     }
145
146     private void assertDependencyGraph(final Map<String, Map<Date, ModuleNodeImpl>> moduleGraph) {
147         for (Entry<String, Map<Date, ModuleNodeImpl>> node : moduleGraph.entrySet()) {
148             String name = node.getKey();
149
150             // Expects only one module revision
151
152             Set<Edge> inEdges = node.getValue().values().iterator().next().getInEdges();
153             Set<Edge> outEdges = node.getValue().values().iterator().next().getOutEdges();
154
155             if (name.equals("a")) {
156                 assertEdgeCount(inEdges, 0, outEdges, 1);
157             } else if (name.equals("b")) {
158                 assertEdgeCount(inEdges, 1, outEdges, 2);
159             } else {
160                 assertEdgeCount(inEdges, 1, outEdges, 0);
161             }
162         }
163     }
164
165     private void assertEdgeCount(final Set<Edge> inEdges, final int i, final Set<Edge> outEdges, final int j) {
166         assertThat(inEdges.size(), is(i));
167         assertThat(outEdges.size(), is(j));
168     }
169
170     private void mockDependency(final ModuleBuilder a, final ModuleBuilder b) {
171         ModuleImport imprt = mock(ModuleImport.class);
172         doReturn(b.getName()).when(imprt).getModuleName();
173         doReturn(b.getName()).when(imprt).getPrefix();
174         doReturn(b.getRevision()).when(imprt).getRevision();
175         a.getImports().put(b.getName(), imprt);
176     }
177
178     private void mockDependency(final Module a, final Module b) {
179         ModuleImport imprt = mock(ModuleImport.class);
180         doReturn(b.getName()).when(imprt).getModuleName();
181         doReturn(b.getRevision()).when(imprt).getRevision();
182         a.getImports().add(imprt);
183     }
184
185     private ModuleBuilder mockModuleBuilder(final String name, final Date rev) {
186         ModuleBuilder a = mock(ModuleBuilder.class);
187         doReturn(name).when(a).getName();
188         Map<String, ModuleImport> map = new HashMap<>();
189         doReturn(map).when(a).getImports();
190         if (rev != null) {
191             doReturn(rev).when(a).getRevision();
192         }
193         return a;
194     }
195
196     private Module mockModule(final String name, final Date rev) {
197         Module a = mock(Module.class);
198         doReturn(name).when(a).getName();
199         Set<ModuleImport> set = Sets.newHashSet();
200         doReturn(set).when(a).getImports();
201         if (rev != null) {
202             doReturn(rev).when(a).getRevision();
203         }
204         return a;
205     }
206 }