2 * Copyright (c) 2016 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 java.util.Objects.requireNonNull;
11 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
12 import static org.junit.jupiter.api.Assertions.assertNotNull;
13 import static org.junit.jupiter.api.Assertions.assertThrows;
14 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFailedFluentFuture;
15 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import java.util.concurrent.ExecutionException;
19 import org.junit.jupiter.api.BeforeEach;
20 import org.junit.jupiter.api.Test;
21 import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier;
22 import org.opendaylight.yangtools.yang.model.api.source.YangTextSource;
23 import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
24 import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactoryConfiguration;
25 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
26 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
27 import org.opendaylight.yangtools.yang.model.spi.source.URLYangTextSource;
28 import org.opendaylight.yangtools.yang.model.spi.source.YangIRSource;
29 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToIRTransformer;
31 class SharedEffectiveModelContextFactoryTest {
32 private final SharedSchemaRepository repository = new SharedSchemaRepository("test");
33 private final SchemaContextFactoryConfiguration config = SchemaContextFactoryConfiguration.getDefault();
35 private SourceIdentifier s1;
36 private SourceIdentifier s2;
40 final var source1 = assertYangText("/ietf/ietf-inet-types@2010-09-24.yang");
41 final var source2 = assertYangText("/ietf/iana-timezones@2012-07-09.yang");
42 s1 = new SourceIdentifier("ietf-inet-types", "2010-09-24");
43 s2 = new SourceIdentifier("iana-timezones", "2012-07-09");
45 final var transformer = TextToIRTransformer.create(repository, repository);
46 repository.registerSchemaSourceListener(transformer);
48 repository.registerSchemaSource(sourceIdentifier -> immediateFluentFuture(source1),
49 PotentialSchemaSource.create(s1, YangTextSource.class, 1));
51 repository.registerSchemaSource(sourceIdentifier -> immediateFluentFuture(source2),
52 PotentialSchemaSource.create(s2, YangTextSource.class, 1));
56 void testCreateSchemaContextWithDuplicateRequiredSources() throws Exception {
57 final var sharedSchemaContextFactory = new SharedEffectiveModelContextFactory(repository, config);
58 final var schemaContext = sharedSchemaContextFactory.createEffectiveModelContext(s1, s1, s2);
59 assertNotNull(schemaContext.get());
63 void testSourceRegisteredWithDifferentSI() throws Exception {
64 final var source1 = assertYangText("/ietf/ietf-inet-types@2010-09-24.yang");
65 final var source2 = assertYangText("/ietf/iana-timezones@2012-07-09.yang");
66 s1 = source1.sourceId();
67 s2 = source2.sourceId();
69 final var provider = AbstractSchemaRepositoryTest.assertYangTextResource(
70 "/no-revision/imported@2012-12-12.yang");
72 provider.register(repository);
74 // Register the same provider under source id without revision
75 final var sIdWithoutRevision = new SourceIdentifier(provider.getId().name());
76 repository.registerSchemaSource(provider, PotentialSchemaSource.create(sIdWithoutRevision,
77 YangIRSource.class, PotentialSchemaSource.Costs.IMMEDIATE.getValue()));
79 final var sharedSchemaContextFactory = new SharedEffectiveModelContextFactory(repository, config);
80 final var schemaContext = sharedSchemaContextFactory.createEffectiveModelContext(
81 sIdWithoutRevision, provider.getId());
82 assertNotNull(schemaContext.get());
86 void testTransientFailureWhilreRetrievingSchemaSource() throws Exception {
87 final SourceIdentifier s3 = new SourceIdentifier("network-topology", "2013-10-21");
89 repository.registerSchemaSource(new TransientFailureProvider(
90 assertYangText("/ietf/network-topology@2013-10-21.yang")),
91 PotentialSchemaSource.create(s3, YangTextSource.class, 1));
93 final var sharedSchemaContextFactory = new SharedEffectiveModelContextFactory(repository, config);
95 var schemaContext = sharedSchemaContextFactory.createEffectiveModelContext(s1, s3);
97 final var exception = assertThrows(ExecutionException.class, schemaContext::get);
98 assertInstanceOf(MissingSchemaSourceException.class, exception.getCause());
100 // check if future is invalidated and resolution of source is retried after failure
101 schemaContext = sharedSchemaContextFactory.createEffectiveModelContext(s1, s3);
102 assertNotNull(schemaContext.get());
105 private static URLYangTextSource assertYangText(final String resourceName) {
106 return new URLYangTextSource(AbstractSchemaRepositoryTest.class.getResource(resourceName));
110 * Schema source provider that fails on first attempt of getSource() and succeeds on every subsequent call
111 * to simulate transient failures of source retrieval.
113 private static final class TransientFailureProvider implements SchemaSourceProvider<YangTextSource> {
114 private final YangTextSource schemaSource;
116 private boolean shouldFail = true;
118 private TransientFailureProvider(final YangTextSource schemaSource) {
119 this.schemaSource = requireNonNull(schemaSource);
123 public ListenableFuture<YangTextSource> getSource(final SourceIdentifier sourceIdentifier) {
126 return immediateFailedFluentFuture(new Exception("Transient test failure."));
129 return immediateFluentFuture(schemaSource);