Remove RevisionSourceIdentifier
[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.hamcrest.CoreMatchers.instanceOf;
12 import static org.hamcrest.MatcherAssert.assertThat;
13 import static org.junit.Assert.assertNotNull;
14 import static org.junit.Assert.assertThrows;
15 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFailedFluentFuture;
16 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
17
18 import com.google.common.util.concurrent.ListenableFuture;
19 import java.util.concurrent.ExecutionException;
20 import org.junit.Before;
21 import org.junit.Test;
22 import org.junit.runner.RunWith;
23 import org.mockito.junit.MockitoJUnitRunner;
24 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
25 import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
26 import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactoryConfiguration;
27 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
28 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
29 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
30 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
31 import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRSchemaSource;
32 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToIRTransformer;
33
34 @RunWith(MockitoJUnitRunner.StrictStubs.class)
35 public class SharedEffectiveModelContextFactoryTest {
36
37     private final SharedSchemaRepository repository = new SharedSchemaRepository("test");
38
39     private final SchemaContextFactoryConfiguration config = SchemaContextFactoryConfiguration.getDefault();
40     private SourceIdentifier s1;
41     private SourceIdentifier s2;
42
43     @Before
44     public void setUp() {
45         final YangTextSchemaSource source1 = YangTextSchemaSource.forResource("/ietf/ietf-inet-types@2010-09-24.yang");
46         final YangTextSchemaSource source2 = YangTextSchemaSource.forResource("/ietf/iana-timezones@2012-07-09.yang");
47         s1 = new SourceIdentifier("ietf-inet-types", "2010-09-24");
48         s2 = new SourceIdentifier("iana-timezones", "2012-07-09");
49
50         final TextToIRTransformer transformer = TextToIRTransformer.create(repository, repository);
51         repository.registerSchemaSourceListener(transformer);
52
53         repository.registerSchemaSource(sourceIdentifier -> immediateFluentFuture(source1),
54             PotentialSchemaSource.create(s1, YangTextSchemaSource.class, 1));
55
56         repository.registerSchemaSource(sourceIdentifier -> immediateFluentFuture(source2),
57             PotentialSchemaSource.create(s2, YangTextSchemaSource.class, 1));
58     }
59
60     @Test
61     public void testCreateSchemaContextWithDuplicateRequiredSources() throws InterruptedException, ExecutionException {
62         final SharedEffectiveModelContextFactory sharedSchemaContextFactory =
63             new SharedEffectiveModelContextFactory(repository, config);
64         final ListenableFuture<EffectiveModelContext> schemaContext =
65                 sharedSchemaContextFactory.createEffectiveModelContext(s1, s1, s2);
66         assertNotNull(schemaContext.get());
67     }
68
69     @Test
70     public void testSourceRegisteredWithDifferentSI() throws Exception {
71         final YangTextSchemaSource source1 = YangTextSchemaSource.forResource("/ietf/ietf-inet-types@2010-09-24.yang");
72         final YangTextSchemaSource source2 = YangTextSchemaSource.forResource("/ietf/iana-timezones@2012-07-09.yang");
73         s1 = source1.getIdentifier();
74         s2 = source2.getIdentifier();
75
76         final SettableSchemaProvider<IRSchemaSource> provider =
77                 SharedSchemaRepositoryTest.getImmediateYangSourceProviderFromResource(
78                     "/no-revision/imported@2012-12-12.yang");
79         provider.setResult();
80         provider.register(repository);
81
82         // Register the same provider under source id without revision
83         final SourceIdentifier sIdWithoutRevision = new SourceIdentifier(provider.getId().name());
84         repository.registerSchemaSource(provider, PotentialSchemaSource.create(
85                 sIdWithoutRevision, IRSchemaSource.class, PotentialSchemaSource.Costs.IMMEDIATE.getValue()));
86
87         final SharedEffectiveModelContextFactory sharedSchemaContextFactory =
88             new SharedEffectiveModelContextFactory(repository, config);
89         final ListenableFuture<EffectiveModelContext> schemaContext =
90                 sharedSchemaContextFactory.createEffectiveModelContext(sIdWithoutRevision, provider.getId());
91         assertNotNull(schemaContext.get());
92     }
93
94     @Test
95     public void testTransientFailureWhilreRetrievingSchemaSource() throws Exception {
96         final SourceIdentifier s3 = new SourceIdentifier("network-topology", "2013-10-21");
97
98         repository.registerSchemaSource(new TransientFailureProvider(
99             YangTextSchemaSource.forResource("/ietf/network-topology@2013-10-21.yang")),
100             PotentialSchemaSource.create(s3, YangTextSchemaSource.class, 1));
101
102         final SharedEffectiveModelContextFactory sharedSchemaContextFactory =
103                 new SharedEffectiveModelContextFactory(repository, config);
104
105         ListenableFuture<EffectiveModelContext> schemaContext =
106                 sharedSchemaContextFactory.createEffectiveModelContext(s1, s3);
107
108         final ExecutionException exception = assertThrows(ExecutionException.class, schemaContext::get);
109         assertThat(exception.getCause(), instanceOf(MissingSchemaSourceException.class));
110
111         // check if future is invalidated and resolution of source is retried after failure
112         schemaContext = sharedSchemaContextFactory.createEffectiveModelContext(s1, s3);
113         assertNotNull(schemaContext.get());
114     }
115
116     /**
117      * Schema source provider that fails on first attempt of getSource() and succeeds on every subsequent call
118      * to simulate transient failures of source retrieval.
119      */
120     private static final class TransientFailureProvider implements SchemaSourceProvider<YangTextSchemaSource> {
121
122         private final YangTextSchemaSource schemaSource;
123         private boolean shouldFail = true;
124
125         private TransientFailureProvider(final YangTextSchemaSource schemaSource) {
126             this.schemaSource = requireNonNull(schemaSource);
127         }
128
129         @Override
130         public ListenableFuture<? extends YangTextSchemaSource> getSource(final SourceIdentifier sourceIdentifier) {
131             if (shouldFail) {
132                 shouldFail = false;
133                 return immediateFailedFluentFuture(new Exception("Transient test failure."));
134             }
135
136             return immediateFluentFuture(schemaSource);
137         }
138     }
139 }