Bump odlparent to 13.1.3
[yangtools.git] / parser / yang-parser-impl / src / test / java / org / opendaylight / yangtools / yang / parser / repo / SharedEffectiveModelContextFactoryTest.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.parser.repo;
9
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;
16
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;
30
31 class SharedEffectiveModelContextFactoryTest {
32     private final SharedSchemaRepository repository = new SharedSchemaRepository("test");
33     private final SchemaContextFactoryConfiguration config = SchemaContextFactoryConfiguration.getDefault();
34
35     private SourceIdentifier s1;
36     private SourceIdentifier s2;
37
38     @BeforeEach
39     void setUp() {
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");
44
45         final var transformer = TextToIRTransformer.create(repository, repository);
46         repository.registerSchemaSourceListener(transformer);
47
48         repository.registerSchemaSource(sourceIdentifier -> immediateFluentFuture(source1),
49             PotentialSchemaSource.create(s1, YangTextSource.class, 1));
50
51         repository.registerSchemaSource(sourceIdentifier -> immediateFluentFuture(source2),
52             PotentialSchemaSource.create(s2, YangTextSource.class, 1));
53     }
54
55     @Test
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());
60     }
61
62     @Test
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();
68
69         final var provider = AbstractSchemaRepositoryTest.assertYangTextResource(
70             "/no-revision/imported@2012-12-12.yang");
71         provider.setResult();
72         provider.register(repository);
73
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()));
78
79         final var sharedSchemaContextFactory = new SharedEffectiveModelContextFactory(repository, config);
80         final var schemaContext = sharedSchemaContextFactory.createEffectiveModelContext(
81             sIdWithoutRevision, provider.getId());
82         assertNotNull(schemaContext.get());
83     }
84
85     @Test
86     void testTransientFailureWhilreRetrievingSchemaSource() throws Exception {
87         final SourceIdentifier s3 = new SourceIdentifier("network-topology", "2013-10-21");
88
89         repository.registerSchemaSource(new TransientFailureProvider(
90             assertYangText("/ietf/network-topology@2013-10-21.yang")),
91             PotentialSchemaSource.create(s3, YangTextSource.class, 1));
92
93         final var sharedSchemaContextFactory = new SharedEffectiveModelContextFactory(repository, config);
94
95         var schemaContext = sharedSchemaContextFactory.createEffectiveModelContext(s1, s3);
96
97         final var exception = assertThrows(ExecutionException.class, schemaContext::get);
98         assertInstanceOf(MissingSchemaSourceException.class, exception.getCause());
99
100         // check if future is invalidated and resolution of source is retried after failure
101         schemaContext = sharedSchemaContextFactory.createEffectiveModelContext(s1, s3);
102         assertNotNull(schemaContext.get());
103     }
104
105     private static URLYangTextSource assertYangText(final String resourceName) {
106         return new URLYangTextSource(AbstractSchemaRepositoryTest.class.getResource(resourceName));
107     }
108
109     /**
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.
112      */
113     private static final class TransientFailureProvider implements SchemaSourceProvider<YangTextSource> {
114         private final YangTextSource schemaSource;
115
116         private boolean shouldFail = true;
117
118         private TransientFailureProvider(final YangTextSource schemaSource) {
119             this.schemaSource = requireNonNull(schemaSource);
120         }
121
122         @Override
123         public ListenableFuture<YangTextSource> getSource(final SourceIdentifier sourceIdentifier) {
124             if (shouldFail) {
125                 shouldFail = false;
126                 return immediateFailedFluentFuture(new Exception("Transient test failure."));
127             }
128
129             return immediateFluentFuture(schemaSource);
130         }
131     }
132 }