2 * Copyright (c) 2014 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.yangtools.yang.parser.repo;
10 import static org.junit.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertFalse;
12 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
13 import static org.junit.jupiter.api.Assertions.assertNotNull;
14 import static org.junit.jupiter.api.Assertions.assertSame;
15 import static org.junit.jupiter.api.Assertions.assertThrows;
16 import static org.junit.jupiter.api.Assertions.assertTrue;
17 import static org.mockito.Mockito.spy;
18 import static org.mockito.Mockito.times;
19 import static org.mockito.Mockito.verify;
21 import java.util.concurrent.ExecutionException;
22 import org.junit.jupiter.api.Test;
23 import org.opendaylight.yangtools.yang.ir.YangIRSchemaSource;
24 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
25 import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier;
26 import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
27 import org.opendaylight.yangtools.yang.model.spi.source.YangTextSource;
28 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToIRTransformer;
30 public class SharedSchemaRepositoryTest {
32 public void testSourceWithAndWithoutRevision() throws Exception {
33 final var sharedSchemaRepository = new SharedSchemaRepository("netconf-mounts");
35 final var idNoRevision = loadAndRegisterSource(sharedSchemaRepository, "/no-revision/imported.yang");
36 final var id2 = loadAndRegisterSource(sharedSchemaRepository, "/no-revision/imported@2012-12-12.yang");
38 var source = sharedSchemaRepository.getSchemaSource(idNoRevision, YangIRSchemaSource.class);
39 assertEquals(idNoRevision, source.get().sourceId());
40 source = sharedSchemaRepository.getSchemaSource(id2, YangIRSchemaSource.class);
41 assertEquals(id2, source.get().sourceId());
44 private static SourceIdentifier loadAndRegisterSource(final SharedSchemaRepository sharedSchemaRepository,
45 final String resourceName) throws Exception {
46 final var sourceProvider = getImmediateYangSourceProviderFromResource(resourceName);
47 sourceProvider.setResult();
48 final var idNoRevision = sourceProvider.getId();
49 sourceProvider.register(sharedSchemaRepository);
54 public void testSimpleSchemaContext() throws Exception {
55 final var sharedSchemaRepository = new SharedSchemaRepository("netconf-mounts");
57 final var remoteInetTypesYang =
58 getImmediateYangSourceProviderFromResource("/ietf/ietf-inet-types@2010-09-24.yang");
59 remoteInetTypesYang.register(sharedSchemaRepository);
60 final var registeredSourceFuture = sharedSchemaRepository.getSchemaSource(
61 remoteInetTypesYang.getId(), YangIRSchemaSource.class);
62 assertFalse(registeredSourceFuture.isDone());
64 final var fact = sharedSchemaRepository.createEffectiveModelContextFactory();
65 final var schemaContextFuture = fact.createEffectiveModelContext(remoteInetTypesYang.getId());
66 assertFalse(schemaContextFuture.isDone());
69 remoteInetTypesYang.setResult();
70 assertEquals(remoteInetTypesYang.getSchemaSourceRepresentation(), registeredSourceFuture.get());
72 // Verify schema created successfully
73 assertTrue(schemaContextFuture.isDone());
74 final var firstSchemaContext = schemaContextFuture.get();
75 assertSchemaContext(firstSchemaContext, 1);
77 // Try same schema second time
78 final var secondSchemaFuture = sharedSchemaRepository.createEffectiveModelContextFactory()
79 .createEffectiveModelContext(remoteInetTypesYang.getId());
81 // Verify second schema created successfully immediately
82 assertTrue(secondSchemaFuture.isDone());
83 // Assert same context instance is returned from first and second attempt
84 assertSame(firstSchemaContext, secondSchemaFuture.get());
88 public void testTwoSchemaContextsSharingSource() throws Exception {
89 final var sharedSchemaRepository = new SharedSchemaRepository("netconf-mounts");
91 final var remoteInetTypesYang =
92 getImmediateYangSourceProviderFromResource("/ietf/ietf-inet-types@2010-09-24.yang");
93 remoteInetTypesYang.register(sharedSchemaRepository);
94 remoteInetTypesYang.setResult();
95 final var remoteTopologyYang =
96 getImmediateYangSourceProviderFromResource("/ietf/network-topology@2013-10-21.yang");
97 remoteTopologyYang.register(sharedSchemaRepository);
98 remoteTopologyYang.setResult();
99 final var remoteModuleNoRevYang =
100 getImmediateYangSourceProviderFromResource("/no-revision/module-without-revision.yang");
101 remoteModuleNoRevYang.register(sharedSchemaRepository);
103 final var fact = sharedSchemaRepository.createEffectiveModelContextFactory();
104 final var inetAndTopologySchemaContextFuture = fact.createEffectiveModelContext(
105 remoteInetTypesYang.getId(), remoteTopologyYang.getId());
106 assertTrue(inetAndTopologySchemaContextFuture.isDone());
107 assertSchemaContext(inetAndTopologySchemaContextFuture.get(), 2);
109 final var inetAndNoRevSchemaContextFuture = fact.createEffectiveModelContext(
110 remoteInetTypesYang.getId(), remoteModuleNoRevYang.getId());
111 assertFalse(inetAndNoRevSchemaContextFuture.isDone());
113 remoteModuleNoRevYang.setResult();
114 assertTrue(inetAndNoRevSchemaContextFuture.isDone());
115 assertSchemaContext(inetAndNoRevSchemaContextFuture.get(), 2);
119 public void testFailedSchemaContext() throws Exception {
120 final var sharedSchemaRepository = new SharedSchemaRepository("netconf-mounts");
122 final var remoteInetTypesYang =
123 getImmediateYangSourceProviderFromResource("/ietf/ietf-inet-types@2010-09-24.yang");
124 remoteInetTypesYang.register(sharedSchemaRepository);
126 final var fact = sharedSchemaRepository.createEffectiveModelContextFactory();
128 // Make source appear
129 final var ise = new IllegalStateException("failed schema");
130 remoteInetTypesYang.setException(ise);
132 final var schemaContextFuture = fact.createEffectiveModelContext(remoteInetTypesYang.getId());
133 final var ex = assertThrows(ExecutionException.class, schemaContextFuture::get);
134 final var cause = assertInstanceOf(MissingSchemaSourceException.class, ex.getCause());
135 assertSame(ise, cause.getCause());
139 public void testDifferentCosts() throws Exception {
140 final var sharedSchemaRepository = new SharedSchemaRepository("netconf-mounts");
142 final var immediateInetTypesYang = spy(
143 getImmediateYangSourceProviderFromResource("/ietf/ietf-inet-types@2010-09-24.yang"));
144 immediateInetTypesYang.register(sharedSchemaRepository);
145 immediateInetTypesYang.setResult();
147 final var remoteInetTypesYang = spy(
148 getRemoteYangSourceProviderFromResource("/ietf/ietf-inet-types@2010-09-24.yang"));
149 remoteInetTypesYang.register(sharedSchemaRepository);
150 remoteInetTypesYang.setResult();
152 final var fact = sharedSchemaRepository.createEffectiveModelContextFactory();
153 final var schemaContextFuture = fact.createEffectiveModelContext(remoteInetTypesYang.getId());
155 assertSchemaContext(schemaContextFuture.get(), 1);
157 final var id = immediateInetTypesYang.getId();
158 verify(remoteInetTypesYang, times(0)).getSource(id);
159 verify(immediateInetTypesYang).getSource(id);
162 private static void assertSchemaContext(final EffectiveModelContext schemaContext, final int moduleSize) {
163 assertNotNull(schemaContext);
164 assertEquals(moduleSize, schemaContext.getModules().size());
167 static SettableSchemaProvider<YangIRSchemaSource> getRemoteYangSourceProviderFromResource(final String resourceName)
169 return SettableSchemaProvider.createRemote(
170 TextToIRTransformer.transformText(YangTextSource.forResource(resourceName)), YangIRSchemaSource.class);
173 static SettableSchemaProvider<YangIRSchemaSource> getImmediateYangSourceProviderFromResource(
174 final String resourceName) throws Exception {
175 return SettableSchemaProvider.createImmediate(
176 TextToIRTransformer.transformText(YangTextSource.forResource(resourceName)), YangIRSchemaSource.class);